Android 内存泄露原理和检测方法

1、什么是内存泄漏

简单地说就是申请了一块内存空间,使用完毕后没有释放掉。它的一般表现方式是程序运行时间越长,占用内存越多,最终用尽全部内存,整个系统崩溃。由程序申请的一块内存,且没有任何一个指针指向它,那么这块内存就泄露了。

 从用户使用程序的角度来看,内存泄漏本身不会产生什么危害,作为一般的用户,根本感觉不到内存泄漏的存在。真正有危害的是内存泄漏的堆积,这会最终消耗尽系统所有的内存。从这个角度来说,一次性内存泄漏并没有什么危害,因为它不会堆积,而隐式内存泄漏危害性则非常大,因为较之于常发性和偶发性内存泄漏它更难被检测到。

最为测试人员,最直观的的感受:新发布的版本过不了多长时间,就处于一种假死的状态,索引查询都很慢,几乎进行不了任何操作,慢慢卡死。o(╥﹏╥)o

2、Android应用内存泄漏的的可能原因(有些地方还是不太懂……开发人员注意下)

1查询数据库后没有关闭游标cursor 

2 构造Adapter时,没有使用 convertView 重用 

3 Bitmap对象不在使用时调用recycle()释放内存 

4 对象被生命周期长的对象引用,如activity被静态集合引用导致activity不能释放

5  BraodcastReceiver,ContentObserver,FileObserver,Cursor在Activity onDeatory或者某类声明周期结束之后一定要unregister或者close掉,否则这个Activity类会被system强引用,不会被内存回收。

6 不要直接对Activity进行直接引用作为成员变量,如果不得不这么做,请用private WeakReference mActivity来做,相同的,对于Service等其他有自己声明周期的对象来说,直接引用都需要谨慎考虑是否会存在内存泄露的可能。

7 对activity的引用应该控制在activity的生命周期之内;

3、Android内存泄露分析(MemoryAnalyzer工具)

MAT(Eclipse Memory Analyzer)被认为是一个“傻瓜式“的堆转储文件分析工具,你只需要轻轻点击一下鼠标就可以生成一个专业的分析报告。和其他内存泄露分析工具相比,MAT 的使用非常容易,基本可以实现一键到位,即使是新手也能够很快上手使用。

参考:https://blog.csdn.net/flb911/article/details/50404175

1)首先要安装MAT工具:

《Android 内存泄露原理和检测方法》

2)使用eclipse 自带的 DDMS 工具分析各线程的内存使用情况,如下图所示

《Android 内存泄露原理和检测方法》
《Android 内存泄露原理和检测方法》 Heap视图界面会定时刷新,在对应用的不断的操作过程中就可以看到内存使用的变化

怎样判断当前进程是否有内存泄漏呢?如上图 data object(数据对象,也就是我们的程序中大量存在的类类型的对象),其Total Size”就是当前进程中所有Java数据对象的内存总量,一般情况下,这个值的大小决定了是否会有内存泄漏:

        a) 不断的操作当前应用,或者重复某一动作,注意观察data object的Total Size值。

        b) 正常情况下Total Size值都会稳定在一个有限的范围内,也就是说如果程序中的的代码逻辑良好

        3) 如果代码中存在对象引用没有释放的情况,则data object的Total Size值在每次GC后不会有明显的回落,随着操作次数的增多Total Size的值会越来越大。(正常情况下,一个虚拟机的进程的内存在64M, 如果内存泄漏会发现 Heap Size 在不断的逼近 64M, 一旦达到这个值时,就会出现退出应用等情况。)

            发生内存泄露,Total Size的值越来越大时,按下“Dump HPROF file”按钮,这个时候会提示设置hprof文件的保存路径。保存后,可以对比log来分析是哪些操作造成了内存泄漏。

《Android 内存泄露原理和检测方法》

3)点击上图图标,导出 hprof 文件,使用MAT 工具进行分析。

3.1)具体分析步骤和过程详见下面链接

https://www.ibm.com/developerworks/cn/opensource/os-cn-ecl-ma/index.html

3.2)eclipse中MAT的 内存泄露分析报告如下图:

《Android 内存泄露原理和检测方法》

3.3)在其中怀疑的地方,点击 Details 就可以看到具体的内存使用情况了:

《Android 内存泄露原理和检测方法》

《Android 内存泄露原理和检测方法》

有一种比较好的方法是,在内存泄漏开始时抓取一个 hprof 文件,在内存泄漏很厉害时,app 濒临崩溃时再抓取一个hprof 文件。

对比看这两个图,就很容易看出来上面的饼图中哪一块存在内存泄漏。

有的时候能直接看出来多了一块。那么我们就从那一块入手进行分析。比较快能得到结果。

4、 使用android shell命令查看内存使用情况

【安装app】  

D:\apk\install2.bat

adb install D:\apk\shangqiubmw.apk

【adb查包名】先启动,然后adb shell dumpsys window w |findstr \/ |findstr name= (查看所有包名:adb shell pm list packages)

判断应该的包名:com.iflytek.smartsq

【查看命令】adb shell dumpsys meminfo com.iflytek.smartsq > D:\apk\dumpLogInfo.txt(包名)(信息重定向)

《Android 内存泄露原理和检测方法》 1

Native Heap是native层的内存堆栈,Dalvik Heap是java层的内存堆栈,如果这二者加起来的内存占用超过了应用最大内存限制就会报OOM异常,剩下的.so mmap是 C 库代码占用的内存,.jar mmap是Java 文件代码占用的内存 ,.apk mmap是apk代码占用的内存,.dex mmap是Dex 文件代码占用的内存

Objects中的Activities表示当前内存中的activity对象的个数,启动一个activity就会生成一个activity对象,当退出activity的时候,activity对象就会被释放,所以反复的进出一个activity界面然后查看Activities的个数有没有保持不变,如果增加了,那么就说明这个activity对象没有被释放,也就是说可能存在内存泄漏,但是具体哪里泄漏了并不知道

5、通过monkey测试检查app内存泄漏和cpu占用 

参考

1) 内存检测bat脚本

内存检测用批处理脚本记录,约5秒记录一次:

脚本   D:\apk\memoryCheck1.bat

报告   D:\apk\memoryCheck_nfo1.txt

《Android 内存泄露原理和检测方法》

右边三列,如果执行了用户事件流10万次后,发现数值一直在增长,那么很有可能是内存泄漏了。

左边第一列,表示app占据内存的大小,比如开四个app程序同时,我们可以比较哪个程序最占用内存,就是通过这个数据!

2) cpu检查bat脚本

脚本   D:\apk\cpuCheck1.bat

报告   D:\apk\cupInfo_1.txt

《Android 内存泄露原理和检测方法》

注:观察CPU%变化

PID 进程id

PR    优先级

CPU%  当前瞬时CPU占用率

S    进程状态:D=不可中断的睡眠状态, R=运行, S=睡眠, T=跟踪/停止, Z=僵尸进程

#THR  程序当前所用的线程数

VSS  Virtual Set Size  虚拟耗用内存(包含共享库占用的内存)

RSS  Resident Set Size 实际使用物理内存(包含共享库占用的内存)

PCY  调度策略优先级,SP_BACKGROUND/SP_FOREGROUND

UID  进程所有者的用户id

Name  进程的名称

    原文作者:云层_
    原文地址: https://www.jianshu.com/p/1a1052749481
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞