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

Nic*_*ckT 19 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
Run Code Online (Sandbox Code Playgroud)

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

启动画面 - >选择模式 - >活动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
Run Code Online (Sandbox Code Playgroud)

过程重复:

                    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
Run Code Online (Sandbox Code Playgroud)

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[]
Run Code Online (Sandbox Code Playgroud)

将非常感谢所有评论

gre*_*gkb 6

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

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

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

此时,除非代码中出现错误,否则我希望与活动A和B相关的任何内存都被收集为垃圾.通常情况下,这就是我认为应用程序中的"内存泄漏".

这通常是由于保留的上下文而发生的,这可能会占用大量内存,因为上下文通常代表大型组件(活动,服务等).

通过"GC根路径" - >"排除弱引用"选项(通过右键单击菜单可以),可以最容易地调查在Dominator Tree中看起来可疑的任何内容.path2gc根视图可能是查找哪些对象持有对象引用以使它们无法释放的最简单方法.

一旦发现保留了意外的引用,就可以通过代码更深入地了解原因.如果它与系统/ OS组件有关,grepcode是你的朋友:)


Din*_*ati 1

接收者的注册和注销会导致内存泄漏

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

通过调试和错误修复来了解这个东西。