如何判断一个Android应用程序是否真的在泄漏内存?

在开发一个应用程序时,我注意到它最终崩溃,因为JVM不能分配更多的内存。 使用adb shell dumpsys meminfo命令,我可以看到分配的本地堆增长,同时切换活动,直到它接近16M,当它崩溃。 我相信我现在已经纠正了代码来阻止这种情况的发生,但是我注意到..meminfo返回的数字有所不同,总体上似乎略有上升。

基本上我不确定当我启动和停止应用程序时是否应该返回相同的值。 我有这些数字,我不知道他们是否意味着我有一个内存泄漏或没有:

在主屏幕上,应用程序在内存中(PID在DDMS中看到),但没有运行

adb shell dumpsys meminfo(相关的PID)给出:

native dalvik other total size: 5248 4039 N/A 9287 allocated: 5227 3297 N/A 8524 free: 12 742 N/A 754 (Pss): 2183 3534 1726 7443 (shared dirty): 1976 4640 876 7492 (priv dirty): 2040 1664 940 4644 

应用程序从主屏幕开始,活动开始是:

启animation面 – >select模式 – >活动1,然后全部使用后退button退出,直到回到主屏幕

meminfo现在:

  native dalvik other total size: 5572 4231 N/A 9803 allocated: 5497 3153 N/A 8650 free: 74 1078 N/A 1152 (Pss): 2479 3614 1742 7835 (shared dirty): 1976 4632 876 7484 (priv dirty): 2336 1740 956 5032 

重复过程:

  native dalvik other total size: 5696 4231 N/A 9927 allocated: 5211 2949 N/A 8160 free: 392 1282 N/A 1674 (Pss): 2515 3713 1742 7970 (shared dirty): 1976 4632 876 7484 (priv dirty): 2372 1840 956 5168 

Eclipse内存分析工具(我没有find所有的信息)报告下面的“泄漏嫌疑人”:

 3,143 instances of "java.lang.Class", loaded by "<system class loader>" occupy 736,760 (35.69%) bytes. Biggest instances: class com.ibm.icu4jni.util.Resources$DefaultTimeZones @ 0x40158fe0 - 165,488 (8.02%) bytes. class android.text.Html$HtmlParser @ 0x400eebd8 - 126,592 (6.13%) bytes. class com.google.googlenav.proto.GmmMessageTypes @ 0x43d183d8 - 56,944 (2.76%) bytes. class org.apache.harmony.security.fortress.Services @ 0x40071430 - 51,456 (2.49%) bytes. class android.content.res.Resources @ 0x4004df38 - 33,584 (1.63%) bytes. class android.text.AutoText @ 0x400f23c8 - 31,344 (1.52%) bytes. Keywords java.lang.Class Details » Problem Suspect 2 8,067 instances of "java.lang.String", loaded by "<system class loader>" occupy 497,304 (24.09%) bytes. Keywords java.lang.String Details » Problem Suspect 3 54 instances of "org.bouncycastle.jce.provider.X509CertificateObject", loaded by "<system class loader>" occupy 256,024 (12.40%) bytes. These instances are referenced from one instance of "java.util.HashMap$HashMapEntry[]", loaded by "<system class loader>" Keywords org.bouncycastle.jce.provider.X509CertificateObject java.util.HashMap$HashMapEntry[] 

所有意见将受到感谢

Solutions Collecting From Web of "如何判断一个Android应用程序是否真的在泄漏内存?"

在MAT中,我几乎从来没有遇到一个实际上是泄漏的“泄漏可疑”。 你真正想要的是在GC扫描之后应该保留的对象。

例如,假设我有一个仪表板活动,可以启动活动A和B.我启动仪表板,然后启动活动A,按下后退button,启动活动B,然后按下后退button。

使用Eclipse Debug视图,可以通过“Cause GC”button强制执行GC采集事件。 现在,点击“转储HPROF文件”button并启动MAT。 点击“Dominator Tree”链接。

在这一点上,我希望任何与活动A和B相关的内存都被收集为垃圾,除非代码中有错误。 通常情况下,这就是我在应用程序中被认定为“内存泄漏”的原因。

这通常是由于保留的上下文而发生的,由于上下文经常表示大的组件(活动,服务等),所以上下文可能会消耗大量的内存。

在Dominator Tree中看起来可疑的任何东西都可以通过“GC Rootspath” – >“排除弱引用”选项(通过右键单击菜单提供)进行调查。 path2gc根视图可能是最简单的方法来find哪些对象持有对象的引用,使他们不能被释放。

一旦你发现意外的引用被保留,它可以通过代码来挖掘更多的理解原因。 如果它与系统/操作系统组件有关,grepcode是你的朋友:)

接收器的注册和注销将导致内存泄漏

例如,如果你已经注册接收器registerReceiver()和应用程序它自己你试图注册它agin没有做注销,那么它也会导致你内存泄漏问题。

从debugging和错误修复的东西了解这个东西。

根据我在创buildAndroid应用程序方面的经验,操作系统似乎在内存中留下了大量的垃圾。 但是,当设备需要重要的东西时,它将(几乎不分青红皂白地)采取任何需要的。 即使它覆盖另一个当前打开的应用程序中的数据。

除此之外,背景中可能会有其他一些事情影响你的数字,所以我不相信我们可以从中得出任何确凿的信息。 如果您创build的应用程序正在泄漏,那么很可能是您正在执行的任何操作都会在其他基于Java的环境中导致内存泄漏。 像http://www.ibm.com/developerworks/library/j-leaks/这样的文章应该有助于解决大多数泄漏的问题&#x3002;

如果我遇到我的应用程序的内存问题,我正在使用android开发工具中包含的ddbms工具的独立版本。

看看这个链接: http : //android-developers.blogspot.com/2009/02/track-memory-allocations.html

有了这个工具,你可以从“java的观点”看看内存消耗情况,这样你就可以看到哪些对象阻塞了大部分的内存。 这将使您能够精确定位所遇到的内存泄漏并优化您的代码。

你给出的输出只给出应用程序中所有使用的内存的概述,但不是如何使用。

在检查内存分析器工具结果时,mat工具不承诺发现memory leak但是根据其脚本显示problemsuspect

MAT工具根据正在运行的应用程序堆分析,制作PIE Chart,Dominator Tree,Path 2 GC视图

开发人员可以根据上述结果分析内存使用情况,并增强其应用程序编程

了解更多关于如何清除内存泄漏的非常好的链接是: 在这里

另外: Google IO 2011video讲解MAT工具 , Document , Blog1和Blog2