玩转LeakCanary

[TODO] 总结了LeakCanary原理及用法。

如何使用LeakCanary

LeakCanary.install()返回一个预先配置好的RefWatcher。该方法同时还会自动使用ActivityRefWatcher,这个对象自动检测Activity.onDestroy()后activity是否有泄漏。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class ExampleApplication extends Application {

public static RefWatcher getRefWatcher(Context context) {
ExampleApplication application = (ExampleApplication) context.getApplicationContext();
return application.refWatcher;
}

private RefWatcher refWatcher;

@Override public void onCreate() {
super.onCreate();
if (LeakCanary.isInAnalyzerProcess(this)) {
// This process is dedicated to LeakCanary for heap analysis.
// You should not init your app in this process.
return;
}
refWatcher = LeakCanary.install(this);
}
}

可以使用RefWatcher用到检查应当被GC的引用:

1
2
3
4
RefWatcher refWatcher = {...};

// We expect schrodingerCat to be gone soon (or not), let's watch it.
refWatcher.watch(schrodingerCat);

可以使用RefWatcher检查fragment的泄漏情况:

1
2
3
4
5
6
7
8
public abstract class BaseFragment extends Fragment {

@Override public void onDestroy() {
super.onDestroy();
RefWatcher refWatcher = ExampleApplication.getRefWatcher(getActivity());
refWatcher.watch(this);
}
}

工作原理

  1. RefWatcher.watch()创建指向被检查对象的KeyedWeakReference
  2. 之后,在后台线程中检查引用是否被清除,如果没有的话GC一下
  3. 如果引用仍然没有清除,则导出heap到.hprof文件,并保存到文件系统
  4. 一个独立的进程启动HeapAnalyzerServiceHeapAnalyzer使用HAHA解析heap dump
  5. HeapAnalyzer在使用key在heap dump中找到KeyedWeakReference,定位到泄漏的引用
  6. HeapAnalyzer计算 到GC根节点的最短强引用 以确定是否有内存泄漏,然后重新构建导致内存泄漏的引用链
  7. 分析结果发送到应用进程的DisplayLeakService,并且通过notification进行提示