gpt4 book ai didi

Android 巨大的 JSONObject toString 出现 OutOfMemoryError

转载 作者:太空狗 更新时间:2023-10-29 13:57:46 27 4
gpt4 key购买 nike

我需要从 SQLite 数据库中读取大量数据并创建格式正确的 JSON。

我目前通过一个名为 RequestPayload 的对象来实现这一点,该对象包含一些 ArrayList,我将我从 SQLite 读取的数据放入其中。

RequestPayload 类有一个 parseJson() 方法,它返回一个 JSONObject,我最终在其上调用了 toString() 方法来获取我最终写入文件的 JSON 字符串。

问题

现在,当我在 SQLite 中获得“少量”数据时,一切正常。当我有大量数据时,会发生这种情况:

06-28 09:55:34.121 10857-6799/it.example.sampler E/AndroidRuntime: FATAL EXCEPTION: Thread-195240
Process: it.example.sampler, PID: 10857
Theme: themes:{com.cyanogenmod.trebuchet=overlay:system, com.android.settings=overlay:system, default=overlay:system, iconPack:system, fontPkg:system, com.android.systemui=overlay:system, com.android.systemui.navbar=overlay:system}
java.lang.OutOfMemoryError: Failed to allocate a 52962812 byte allocation with 16764752 free bytes and 41MB until OOM
at java.lang.StringFactory.newStringFromChars(Native Method)
at java.lang.AbstractStringBuilder.toString(AbstractStringBuilder.java:629)
at java.lang.StringBuilder.toString(StringBuilder.java:663)
at org.json.JSONStringer.toString(JSONStringer.java:430)
at org.json.JSONObject.toString(JSONObject.java:690)
at it.example.sampler.controllers.network.RequestBodyEncoder.serialise(RequestBodyEncoder.java:69)
at it.example.sampler.controllers.network.RequestBodyEncoder.createPacket(RequestBodyEncoder.java:50)
at it.example.sampler.services.FileStoreRunnable.run(FileStoreRunnable.java:57)
at java.lang.Thread.run(Thread.java:818)

06-28 09:55:34.509 10857-10857/it.example.sampler E/WindowManager: android.view.WindowLeaked: Activity it.example.sampler.ui.StartSamplingActivity has leaked window com.android.internal.policy.PhoneWindow$DecorView{74710d V.E...... R......D 0,0-1026,494} that was originally added here
at android.view.ViewRootImpl.<init>(ViewRootImpl.java:372)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:299)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:86)
at android.app.Dialog.show(Dialog.java:319)
at it.example.sampler.ui.StartSamplingActivity.executeStop(StartSamplingActivity.java:305)
at it.example.sampler.ui.StartSamplingActivity.onClickedButton(StartSamplingActivity.java:256)
at it.example.sampler.ui.StartSamplingActivity$3.onClick(StartSamplingActivity.java:190)
at android.view.View.performClick(View.java:5204)
at android.view.View$PerformClick.run(View.java:21158)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5461)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

代码

错误行来自这个方法:

private String serialise() throws JSONException {
// Serialise
String sampleString = mPayload.parseJSON().toString(); // THIS LINE

Logger.get().d(LOG_TAG, "Serialised payload: -> " + sampleString);
return sampleString;
}

如果我正确地获得了 LogCat,则错误是在执行 toString() 方法期间出现的,而且 JSON 对象似乎太大了。

我该如何处理这种情况?


更新:回答询问 JSONObject 大小的@YashJain 评论。

采样持续 2 小时后,我得到了一个包含以下内容的 JSON:

  • 12 包含 155.432 个float
  • 的 JSONArray
  • 2 包含 8.393 个float
  • 的 JSONArray
  • 1 包含 8.393 个自定义对象的 JSONArray,每个对象包含 5 个 float(和一个 String)
  • 1 包含 155.432 个 int
  • 的二维数组

就字节而言,因为 Float 是由 4 个字节组成的(我希望我已经正确地完成了微积分)我得到了大约:

(12 * 155432 * 4) + (2 * 8393 * 4) + (1 * 8393 * 5) + (1 * 155432 * 4) ~= 8.191.573 bytes

更新:有人问我使用的压缩算法。我通过 DeflaterDeflaterOutputStream Java 类使用 ZLIB

因此流程是:

  • 示例数据 -> 将它们存储在 SQLite
  • SQLite 中读取 -> 在内存中构建 RequestPayload 对象
  • RequestPayload 对象转换为 JSONObject(使用自定义解析器)。
  • JSONObject 转换为字符串(使用 JSONObject toString() 方法)
  • 压缩字符串字节(使用 getBytes())-> 以 Base64 编码
  • 将最终的 Base64 字符串发送到服务器

编辑:为了解决“可能的重复标志”问题,我在研究过程中没有看到这个问题,因为它使用了 largeHeap 指令(我不使用),这对我没有帮助.也没有公认的答案,唯一的答案实际上并没有提供切实可行的解决方案。

最佳答案

很抱歉没有再提供任何反馈,我一直忙于其他工作,这在我的优先队列中排在最后。

无论如何,真正对我有用的是使用 Google GSON 库。

我的序列化方法变得很简单:

private String serialise() {
// Serialise
return mPayload.toStringFromGSON();
}

Payload 中的方法 toStringFromGSON() 是:

public String toStringFromGSON() {
GsonBuilder gsonBuilder = new GsonBuilder();
Gson gson = gsonBuilder.create();

return gson.toJson(this);
}

无论如何,我认为这只能算是一个临时补丁。事实上,我注意到应用程序使用的内存在这个阶段急剧增加,因此我认为这个问题只是被推迟了,它最终会在更重的负载下发生。

关于Android 巨大的 JSONObject toString 出现 OutOfMemoryError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38073576/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com