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

标签 android

在开发应用程序时,我注意到它最终崩溃了,因为 JVM 无法分配更多内存。使用 adb shell dumpsys meminfo 命令,我可以看到分配的 native 堆在切换 Activity 时增长,直到它接近 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

应用程序从主屏幕启动,启动的 Activity 是:

启动画面 -> 选择模式 -> Activity 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 内存分析器工具(我没有找到所有信息)报告以下内容 “泄密嫌疑人”:

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

所有评论将不胜感激

最佳答案

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

例如,假设我有一个 Dashboard Activity ,可以启动 Activity A 和 B。我启动 Dashboard,然后启动 Activity A,按返回按钮,启动 Activity B,然后按返回按钮。

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

此时,我希望与 Activity A 和 B 相关的任何内存都被作为垃圾收集,除非代码中出现错误。通常,这就是我认为应用程序中的“内存泄漏”。

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

任何在支配树中看起来可疑的东西都可以通过“路径到 GC 根”->“排除弱引用”选项(通过右键菜单可用)最容易地进行调查。 path2gc Root View 可能是查找哪些对象持有对无法释放的对象的引用的最简单方法。

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

关于android - 如何判断 Android 应用程序是否真的在泄漏内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5097211/

相关文章:

java - Android 应用程序在蓝牙 LE 写入时崩溃

android - Searchview 在 flavor 构建中不起作用

Android:如何使 GPS 试图找到锁超时?

android - Xamarin.forms 在 knox standard sdk 5.7 中激活 Kiosk 模式后启用状态栏

java - 如何使用 Toast 获取按钮的文本

android - 如何更改 Vuforia AR 相机对焦模式?

java - Android 项目中的 Creative SDK 图像编辑器 UI

javascript - React Native 版本不匹配。无法在Android Studio中生成构建,但通过VS代码react-native run-android可以正常运行

android - 如果收到的 TTS 太长,onUtteranceCompleted() 会丢失

java - 使用另一个 fragment 中的按钮打开 fragment