一、引言
内存泄露一直是Android开发中需要避免的问题,因此发现和定位内存泄露就是我们治理内存泄露问题的首要动作。目前市面上最流行的内存泄露排查组件非大名鼎鼎的***LeakCanary***莫属了,它能非常方便直观把内存泄漏处的引用链展示出来,有助于我们的快速定位。另外,其使用方式也十分简单友好。对于开发者而言,仅满足使用还是不够的,尽量知其所以然,于是就有了这篇源码的解析。
二、使用和原理
源码分析基于LeakCanary版本1.6.3
2.1 使用方式
LeakCanary可以检测具体Activity和Fragment是否存在内存泄露,也可以对想要观察的对象进行检测。它的使用十分简单,以检测Activity为例,以下几行代码即可。
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
if (!LeakCanary.isInAnalyzerProcess(this)) {
LeakCanary.install(this);
}
}
}
自定义Application类,调用LeakCanary.install()
方法即可。
2.2 检测原理
LeakCanary的检测原理是:
弱引用对象在其包装对象被回收后(弱引用对象创建时,传入了引用队列),该弱引用对象会被加到引用队列中(ReferenceQueue)。
通过在ReferenceQueue中检测是否有目标对象的弱引用对象存在,即可判断目标对象是否被回收。
例如:
......
Activity mActivity;
......
ReferenceQueue<Activity> mQueue = new ReferenceQueue<>();
WeakReference<Activity> mWeakReference = new WeakReference<>(mActivity, mQueue);
......
在创建目标对象mActivity
的弱引用对象时,如果构造方法中传入了引用队列mQueue
,那么当mActivity
对象被回收时,mWeakReference
对象将会被添加到引用队列mQueue
中。
三、源码分析
了解了检测原理后,现在以检测Activity是否存在内存泄露为例,来详细分析下实现源码。
3.1、使用入口install
方法
public static @NonNull RefWatcher install(@NonNull Application application) {
return refWatcher(application).listenerServiceClass(DisplayLeakService.class)
.excludedRefs(AndroidExcludedRefs.createAppDefaults().build())
.buildAndInstall();
}
进行一些初始化的构造,重点在buildAndInstall
方法
3.2、buildAndInstall
方法
public @NonNull RefWatcher buildAndInstall() {
if (LeakCanaryInternals.installedRefWatcher != null) {
throw new UnsupportedOperationException("buildAndInstall() should only be called once.");
}
// ①
RefWatcher refWatcher = build();
// ②
if (refWatcher != DISABLED