LeakCanary主要用在Android中分析内存泄漏。何为内存泄漏?简单说便是,当一个对象所占用堆存储空间该被系统GC回收时,却由于种种原因没有被回收,那么这些内存就称为泄漏的内存。举个例子,退出一个Activity时,这时这个Activity该被回收,但是因为Activity内声明的Thread还在跑,Thread持有Activity的引用,导致Activity无法被回收,这时就造成了内存泄漏。
LeakCanary是Square公司出品,这是家做移动支付的公司,但对于开发者来说,这就是家开源库公司,因为不少当下较为流行的三方库,都是出自Square,比如OkHttp,Retrofit,Picasso,这几个较为常用。
1. 使用
- Github库地址
- 文档地址
接入十分简单,在build.gradle中,加入下面的依赖,即可1
2
3
4dependencies {
// debugImplementation because LeakCanary should only run in debug builds.
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.9.1'
}
2. 工作步骤
当LeakCanary被安装后,它会自动检测,并报告应用中的内存泄漏,分为4个步骤:
- 检测存活的对象
- 输出堆信息
- 分析堆信息
- 将泄漏分类
2.1 检测存活对象
LeakCanary注册了Android生命周期的检测,会自动检测执行过onDestroy方法的Activity和Fragment,这些都应该被GC回收。ObjectWatcher会持有这些对象的弱引用,LeakCanary会检测下面这些对象
- 被销毁的Activity实例
- 被销毁的Fragment实例
- 被销毁的Fragment View实例
- 被清理的ViewModel实例
如果被ObjectWatcher持有的对象,在5秒后依然没有被清理,那么就会执行GC,之后,若被持有object依然存在没有被回收,那么就有可能泄漏了。
2.2 输出堆信息
当存活的对象到达阈值的时候,LeakCanary就会将Java堆信息输出到一个.hprof文件中,这个操作可能会卡住应用一小段时间,会有Toast给出提示。
2.3 分析堆信息
Shark: Smart Heap Analytisis Reports for Kotlin,是一个分析堆信息的工具
LeakCanary使用Shark来分析hprof文件,并定位存活对象在堆信息中的位置。对于每一个存活的对象,LeakCanary都会找到阻止这个对象被系统GC回收的引用路径。当分析完成时,会有一个包含汇总信息的通知提示,点开便可查看详细信息。
2.4 泄漏分类
LeakCanary将她从应用中发现的泄漏分为两类,一类是应用自身的泄漏,一类是依赖库的泄漏。依赖库泄漏是三方库中已知的bug导致,我们无法控制。这个泄漏对我们应用产生了影响,但不幸的是,我们无法修复。
3. 总结
LeakCanary关键部分,就是如何检测泄漏对象:通过注册回调监听Activity和Fragment的生命周期,在其destroy之后,创建WeakReference,然后就是等待5秒,理想状态下这个时间内会被GC回收,如果5秒还存活,那么就手动调用GC,依然存活的就考虑是泄漏了,最后就是分析堆、查引用路径。下面这个文章对里面的代码做了分析,但是版本不是最新,和最新的可能会有一些出入,但大体逻辑是一样的。
全解系列:内存泄漏定位工具LeakCanary