如何判断Android应用程序是否实际泄漏了内存?

时间:2011-02-23 21:14:28

标签: android

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

基本上我不确定在启动和停止应用程序时它们是否应该返回相同的值。我有这些数字,我不确定它们是否表示我有内存泄漏:

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

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

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

启动画面 - >选择模式 - >活动1,然后使用后退按钮退出, 直到回到主屏幕

现在是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 Memory Analyzer Tool(我找不到所有提供的信息)报告如下 '泄密嫌疑人':

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[]

将非常感谢所有评论

5 个答案:

答案 0 :(得分:6)

在MAT中,我几乎从未遇到过实际上是泄密的“泄漏嫌疑人”。您真正需要的是在GC扫描后保留的对象,这些对象不应该被保留。

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

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

此时,我预计任何与活动A&amp; A相关的记忆。除非代码中有错误,否则B已被收集为垃圾。通常情况下,这就是我认为应用程序中的“内存泄漏”。

这通常是由于保留的上下文而导致的,因为上下文通常代表大型组件(活动,服务等),因此会占用大量内存。

通过“GC根源路径” - &gt;可以最容易地调查Dominator Tree中看起来可疑的任何内容。 “排除弱引用”选项(可通过右键单击菜单获得)。 path2gc根视图可能是查找哪些对象持有对象引用以便无法释放它们的最简单方法。

一旦发现意外的引用被保留,可能需要更多地挖掘代码才能理解原因。如果它与系统/ OS组件有关,grepcode是你的朋友:)

答案 1 :(得分:1)

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

例如,如果您已经使用registerReceiver()注册了接收器,并且在应用程序中它自己尝试注册它而不进行取消注册,则会导致内存泄漏问题。

通过调试和修复错误来了解这一点。

答案 2 :(得分:1)

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

除此之外,背景中可能还有其他一些事情会影响您的数字,所以我不相信我们可以从中获取任何结论性信息。如果您创建的应用程序正在泄漏,那么很可能您正在做的事情会导致任何其他基于Java的环境中的内存泄漏。像http://www.ibm.com/developerworks/library/j-leaks/这样的文章可以帮助修复大多数泄漏问题。

答案 3 :(得分:0)

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

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

使用此工具,您可以从“Java的角度”查看内存消耗,这样您就可以看到哪些对象阻挡了大部分内存。这将使您能够精确定位您遇到的内存泄漏并优化代码。

您提供的输出仅概述了应用程序中的所有已用内存,但未概述其使用方式。

答案 4 :(得分:0)

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

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

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

了解更多有关如何消除内存泄漏的非常好的链接是:here

另外:Google IO 2011 video explaining MAT toolDocumentBlog1Blog2