使用
- module 下的 dependencies 中添加依赖
dependencies {
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3'
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3'
}
- Application 中初始化
public class App extends Application {
@Override
public void onCreate() {
super.onCreate();
LeakCanary.install(this);
}
}
两步就成功集成了,当出现内存泄漏时会提示
In com.renxl.leakcanarydemo:1.0:1. * com.renxl.leakcanarydemo.SecondActivity has leaked:
* GC ROOT static com.renxl.leakcanarydemo.Single.view // 发生泄漏的根源
* references android.view.View.mContext // 发生泄漏的对象
* leaks com.renxl.leakcanarydemo.SecondActivity instance // 发现泄漏的对象的实例
* Reference Key: 0491c0f8-6706-4ee8-926d-fcbc91f06717
* Device: Meizu Meizu m3 note m3note
* Android Version: 5.1 API: 22 * Durations: watch=5020ms, gc=131ms, heap dump=6026ms, analysis=120163ms
手机通知栏也会提示
``
GC ROOT static Single.view
references View.mContext
leaks SecondActivity instance
``
可以快速的定位内存泄漏的位置
原理
- Application 中初始化 LeakCanary 时得到 RefWatcher 对象用于监控那些本该被回收的对象,同时启用一个 ActivityRefWathcer,用于自动检测 Activity.onDestory 之后发生泄漏的 activity
- 在 onDestory 中调用 RefWatcher.watch() 方法,该方法会创建一个 KeyedWeakReference 到要被监控的对象
- 在后台线程检查引用是否被清除,如果没有,调用 GC
- 如果引用还未清除,把 heap 内存 dump 到 APP 对应的文件系统中的 .hprof 文件
- 另一进程中的 HeapAnalyzerService 有一个 HeapAnalyzer 来解析这个文件
- 通过唯一的 refrence key ,HeapAnalyzer 找到 KeyedWeakRefrence ,定位内存泄漏
- HeapAnalyzer 计算到 GC roots 的最短强引用路径,并确定是否是泄漏,如果是,建立导致泄漏的引用链
- 引用链传递到 APP 进程中的 DisplayLeadService,并以通知形式展示出来。
进阶
上传 lead trace 到服务器
我们可以自定义 LeakService 继承 DisplayLeakService ,在有内存泄漏时,将泄漏信息传递至服务器
注册 LeakService
在初始化 LeakCanary 时使用我们自定义的 LeakService