1、需要提前准备的两个工具,并完成配置
- eclipse的MAT内存分析工具,它的独立安装版本下载地址如下:
- square的leakcanary库 ,并参考readme配置。
2、如何知道是否发生内存泄漏
leakcanary库发布之前
为了评估应用是否发生内存泄漏,需要打开android studio的mermory monitor工具,一直玩耍需要测试的应用和手动触发gc,同时观察实时图例中的内存消耗情况。如果发现应用的内存一直处于增长状态,那么该应用有可能产生了内存泄漏。
dump文件格式转换
hprof-conv dump.hprof converted-dump.hprof
leakcanary库发布之后
leakcanary库可以自动检测当前fragment或者activity有没发生泄漏,如果发生了内存泄漏,手机的通知栏会对用户进行通知,并提示简易的泄漏堆栈信息,同时,leak库还会在手机的download文件夹中生成dump文件,该文件记录了当前时刻应用详细的消耗的内存信息,包括存在的类对象,类对象数量等。该dump文件借助MAT内存分析工具即可分析造成内存泄漏的代码段。
下面举一个真实项目的例子。下图是在调试分享库时获取到的内存泄漏信息。
从leakcanary的通知中可以得知,我们的SinaAssistActivity类发生了泄漏。我们从打开MAT工具,并用该工具打开dump文件。切换到OQL窗口,输入的查询命令可以获得所有在内存中的Activities。
select * from instanceof android.app.Activity
点击一个SinaAssistActivity对象,右键选中Path to GC roots。
从上图可知,com.github.thinwonton.share.core.ui.SinaAssistActivity 被三个类持有,分别是KeyedWeakReference、SinaShareHandler和PhoneWindow$DecorView。其中,KeyedWeakReference是leakcanary库的,PhoneWindow$DecorView是安卓系统的窗口类,这两个类不需要理睬。真正造成内存泄漏的原因是,SinaShareHandler中的mWeiboShareAPI属性一直持有SinaAssistActivity对象,即时在SinaAssistActivity#onDestroy后还不释放。此时,我们回到SinaShareHandler类中需找原因,分析如下:
SinaShareHandler中的mWeiboShareAPI属性是静态static的,我们在SinaShareHandler类的init初始化方法中给mWeiboShareAPI赋值,并令mWeiboShareAPI持有了SinaAssistActivity对象。但是,并没有在其它代码段中释放mWeiboShareAPI,由于static关键词使mWeiboShareAPI对象的生命周期持续到app结束,因此,SinaAssistActivity对象也没有得到及时释放。为了修复该bug,我们把SinaShareHandler类中mWeiboShareAPI对象声明为非static对象。