Android:解包导致内存不足异常。如何检查物体?

发布于 2024-09-28 12:22:07 字数 2629 浏览 8 评论 0原文

设置如下:

  • 我有一个包含项目列表的活动(从服务器更新,由普通 java 类表示)。这些项目通过自定义 BaseAdapter 和每行的自定义视图呈现。
  • 这些项目实现了 Parcelable,因此当屏幕旋转时,这些项目将作为 ParcelableArrayList 保存在包中,然后在不返回到服务器的情况下进行恢复。

到目前为止,这是一个相当简单的设置,但是我想将其中一个项目传递给另一个活动。 Bundle 有一个“pubExtra(String, Parcelable)”方法,我想用它来将对象放在那里,然后通过意图传递。当我这样做时,设备由于 OutOfMemoryException 开始强制关闭。似乎在尝试解包该对象时,它请求 ~30mb(!)

似乎该对象必须持有对其他内容的引用,因为该对象本身只包含一些 int/float/String 字段和相关方法。我无法通过查看代码或调试检查器来追踪这一点,并且我不知道如何有效地使用堆查看器。

有什么建议吗?

这是堆栈跟踪

/dalvikvm-heap( 5876): Out of memory on a 29098436-byte allocation.
I/dalvikvm( 5876): "main" prio=5 tid=1 RUNNABLE
I/dalvikvm( 5876):   | group="main" sCount=0 dsCount=0 s=N obj=0x4001d8d0 self=0xccc8
I/dalvikvm( 5876):   | sysTid=5876 nice=0 sched=0/0 cgrp=default handle=-1345017816
I/dalvikvm( 5876):   | schedstat=( 1107116708 1124999998 2626 )
I/dalvikvm( 5876):   at java.util.ArrayList.<init>(ArrayList.java:~84)
I/dalvikvm( 5876):   at android.os.Parcel.readArrayList(Parcel.java:1460)
I/dalvikvm( 5876):   at android.os.Parcel.readValue(Parcel.java:1792)
I/dalvikvm( 5876):   at android.os.Parcel.readMapInternal(Parcel.java:2007)
I/dalvikvm( 5876):   at android.os.Bundle.unparcel(Bundle.java:208)
I/dalvikvm( 5876):   at android.os.Bundle.containsKey(Bundle.java:249)
I/dalvikvm( 5876):   at <mypackage>.BaseDetailsActivity.isInModifyState(BaseDetailsActivity.java:184)
I/dalvikvm( 5876):   at <mypackage>.DetailsActivity.onCreate(DetailsActivity.java:230)
I/dalvikvm( 5876):   at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
I/dalvikvm( 5876):   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)
I/dalvikvm( 5876):   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
I/dalvikvm( 5876):   at android.app.ActivityThread.access$2300(ActivityThread.java:125)
I/dalvikvm( 5876):   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
I/dalvikvm( 5876):   at android.os.Handler.dispatchMessage(Handler.java:99)
I/dalvikvm( 5876):   at android.os.Looper.loop(Looper.java:123)
I/dalvikvm( 5876):   at android.app.ActivityThread.main(ActivityThread.java:4627)
I/dalvikvm( 5876):   at java.lang.reflect.Method.invokeNative(Native Method)
I/dalvikvm( 5876):   at java.lang.reflect.Method.invoke(Method.java:521)
I/dalvikvm( 5876):   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
I/dalvikvm( 5876):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
I/dalvikvm( 5876):   at dalvik.system.NativeStart.main(Native Method)

Here's the setup:

  • I have an activity with a list of items (updated from server, represented by a plain java class). The items are rendered via a custom BaseAdapter and custom View for each row.
  • The items implement Parcelable, so that when the screen is rotated, the items are saved in the bundle as a ParcelableArrayList, then restored without going back to the server.

So far, this is a fairly straightforward setup, however I want to pass one of these items to another activity. Bundle has a "pubExtra(String, Parcelable)" method, which I wanted to use to put the object there, then pass via the intent. When I did this, the device started getting a force close due to an OutOfMemoryException. It seems when trying to unparcel the object, it requests ~30mb(!)

It seems like the object must be holding references to something else, since the object itself only contains a few int/float/String fields and related methods. I haven't been able to track this down by looking at the code or debug inspector and I don't know how to use the Heap viewer effectively.

Any suggestions?

Here's the stacktrace

/dalvikvm-heap( 5876): Out of memory on a 29098436-byte allocation.
I/dalvikvm( 5876): "main" prio=5 tid=1 RUNNABLE
I/dalvikvm( 5876):   | group="main" sCount=0 dsCount=0 s=N obj=0x4001d8d0 self=0xccc8
I/dalvikvm( 5876):   | sysTid=5876 nice=0 sched=0/0 cgrp=default handle=-1345017816
I/dalvikvm( 5876):   | schedstat=( 1107116708 1124999998 2626 )
I/dalvikvm( 5876):   at java.util.ArrayList.<init>(ArrayList.java:~84)
I/dalvikvm( 5876):   at android.os.Parcel.readArrayList(Parcel.java:1460)
I/dalvikvm( 5876):   at android.os.Parcel.readValue(Parcel.java:1792)
I/dalvikvm( 5876):   at android.os.Parcel.readMapInternal(Parcel.java:2007)
I/dalvikvm( 5876):   at android.os.Bundle.unparcel(Bundle.java:208)
I/dalvikvm( 5876):   at android.os.Bundle.containsKey(Bundle.java:249)
I/dalvikvm( 5876):   at <mypackage>.BaseDetailsActivity.isInModifyState(BaseDetailsActivity.java:184)
I/dalvikvm( 5876):   at <mypackage>.DetailsActivity.onCreate(DetailsActivity.java:230)
I/dalvikvm( 5876):   at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
I/dalvikvm( 5876):   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)
I/dalvikvm( 5876):   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
I/dalvikvm( 5876):   at android.app.ActivityThread.access$2300(ActivityThread.java:125)
I/dalvikvm( 5876):   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
I/dalvikvm( 5876):   at android.os.Handler.dispatchMessage(Handler.java:99)
I/dalvikvm( 5876):   at android.os.Looper.loop(Looper.java:123)
I/dalvikvm( 5876):   at android.app.ActivityThread.main(ActivityThread.java:4627)
I/dalvikvm( 5876):   at java.lang.reflect.Method.invokeNative(Native Method)
I/dalvikvm( 5876):   at java.lang.reflect.Method.invoke(Method.java:521)
I/dalvikvm( 5876):   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
I/dalvikvm( 5876):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
I/dalvikvm( 5876):   at dalvik.system.NativeStart.main(Native Method)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

静若繁花 2024-10-05 12:22:07

我遇到了同样的问题,归结为:我犯了错误,我的一个变量没有按照正确的顺序写入。我认为 Parcelable 的工作水平非常低。

我的猜测是,在低级别上,它尝试在错误的内存位置读取数组列表,并且它从未得到“停止读取!”的提示。信号。因此,它继续疯狂地读取,直到堆空间达到应用程序限制。 *我还猜测您可能有/正在遇到类似的问题

底线:仔细检查您的 Parcelable 读取和写入函数,并确保它们以相同的顺序读取/写入变量

  • 即使这是一个很长的问题不久前。我通过谷歌找到了这个页面,所以继续发布这个页面,以防其他人遇到同样的问题。

编辑:我也会推荐 elevine 的建议,并鼓励对其进行投票。这实际上帮助我将范围缩小到 Parcel 对象中的 ArrayList

I had the same problem that boiled down to this: I slipped up and one of my variables wasn't being written in the correct sequence. I think Parcelable works on a very low level.

My guess is that on the low level, it tried to read an arraylist at the wrong memory location, and it never got the "Stop reading!" signal. So, it kept reading like crazy until the Heap Space hit the app limit. *I'm also guessing that you probably had/are having a similar issue

Bottom line: double-check your Parcelable reading and writing functions and make sure they are reading/writing the variables in the same sequence

  • Even though this was asked a pretty long time ago. I found this page via Google so went ahead and posted this in case anyone else out there got the same problem.

Edit: I would recommend elevine's suggestion as well and I encourage voting it up. This actually helped me narrow it down to ArrayLists in the Parcel object

追星践月 2024-10-05 12:22:07

您应该尝试使用 Eclipse 内存分析器工具 。将其作为 Eclipse 的插件安装,然后使用 DDMS 中的“转储 Hprof 文件”按钮(看起来像“设备”选项卡上带有向下箭头的绿色圆柱体)。安装 MAT 后,Eclipse 应该只需启动它并显示一些视图即可检查你的记忆。

如果你发布一些代码,也许有人也能找到问题。

You should try using the Eclipse Memory Analyzer Tool . Install it as a plugin to Eclipse, and then use the "Dump Hprof file" button in DDMS (looks like a green cylinder with a down arrow on the Devices tab"). With MAT installed, Eclipse should just launch it with some views to inspect your memory.

If you post some of your code, someone might be able to find the problem too.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文