Android内存泄漏-MAT篇

拥有回忆 提交于 2020-04-27 06:25:33

    最近项目中的内存越来越大,于是了解关于Android内存分析相关的知识,用以解决实际问题。现在有很多好的内存分析工具比如:LeakCanary、DDMS、mat。

    一、首先简单介绍下LeakCanary:

    在build.gradle文件中添加

 在应用的application onCreate方法中添加LeakCanary.install(this),如下

 应用运行起来后,LeakCanary会自动去分析当前的内存状态,如果检测到泄漏会发送到通知栏,点击通知栏就可以跳转到具体的泄漏分析页面。

    二、下面重点介绍下DDMS结合mat分析内存泄漏问题。

使用mat分析首先要通过eclipse或是Android studio生成hprof文件,然后使用命令cd到Android sdk的目录下:

cd /usr/local/android/sdk/tools  //改成自己的sdk目录
hprof-conv com.scics.huaxi.hprof ff.hprof  //转换格式命令

这样就生成可供mat分析的hprof文件。http://www.eclipse.org/mat/ 此处可下载mat,可以下载独立版亦可以下载eclipse插件版,本人下的是独立版本。将我们得到的hprof文件导入mat中得如下结果:

深色区域的3.6MB、9.3MB、9.6MB标示有内存泄漏的

mat的菜单从左到右Overview、Histogram、Dominator_tree、QQL等

1、我们先来看Histogram视图

        这里简单介绍下

状态栏的意思class Name很简单,Objects标示该对象出现的次数,Shallow Heap标示对象本身所占的内存空间,Retained Heap标示对象本身及其直接饮用或间接引用一起所占的内存空间。一般来说若Shallow Heap和Retained Heap的差距很大就需要仔细分析该对象是不是产生了泄漏,因为它若释放了那么与它直接或间接关联的对象很多都有可能(只能说可能会释放,也许还会有其他地方产生了此对象的引用)释放。

可以看到

shallow heap和Retained head差距很大,并且对于Android来说一般TextView、LinearLayout的对象用过之后就会释放,这里还存在这么多。应该是某些activity没有被销毁导致的。故下面对TextView来分析:

Path To GC Roots -> exclude all phantim/weak/soft etc. references:查看这个对象的GC Root,不包含虚、弱引用、软引用,剩下的就是强引用。从GC上说,除了强引用外,其他的引用在JVM需要的情况下是都可以 被GC掉的,如果一个对象始终无法被GC,就是因为强引用的存在,从而导致在GC的过程中一直得不到回收,因此就内存溢出了。可以得到如下:

展开第一个查看查看代码得到AudioManager是单例类它的mInstance对象持有AudioRecordButton的引用,AudioRecordButton的对象又持有AskDetail的引用,故而导致activity AskDetail没有释放导致内存泄漏。  此处修改在OnDestory中注销AudioRecordButton的监听器。ps:在Android代码中这种类似监听器的观察者模式用的非常多,最好在destory的时候都要反注入,防止对象保有activity的引用导致activity不能释放。

mAudioRecordBtn.setAudioFinishRecorderListener(null);
mAudioRecordBtn = null;

2、QQL查询

若你怀疑某个类有内存泄漏,则可以直接通过QQL语句查询该类在内存中的情况如上。

3、Dominator_tree视图

将内存中对象按从大到小的顺序排列和Histogram视图一样分析大的对象,可以通过查看对下的List Objects--->with incoming reference/with outgoing reference或者merge shortest path to gc root来查看内存泄漏的根本原因。

  • List objects -> with incoming references:查看这个对象持有的外部对象引用
  • List objects -> with outgoing references:查看这个对象被哪些外部对象引用
  • merge shortest path to gc root -> exclude all phantim/weak/soft etc. references:查看这个对象的gc root去掉若引用、虚引用、软引用。从而快速得到到这个对象没有释放的根本原因。

通过对内存的分析,已让我知道程序更容易出现内存泄漏的地方。此为必经之路。

本篇完

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!