创建一个refWatcher,启动一个ActivityRefWatcher,通过actvityLifecyclerCallbacks 把Activity的onDestory生命周期关联,最后在线程池中去开始分析对象的引用。
原理
当Activity或者Fragment销毁时,启动一个ActivityRefWatcher,通过actvityLifecyclerCallbacks 关联onDestoryed()方法。用一个弱引用去包装当前销毁的Activity或者Fragment,并且将它与本地的一个ReferenceQueue队列关联。我们知道如果GC触发了,系统会将当前的引用对象存入队列中。如果没有被回收,队列中则没有当前的引用对象。所以LeakCanary会去判断,ReferenceQueue是否有当前观察的Activity或者Fragment的引用对象,第一次判断如果不存在,就去手动触发一次GC,然后做第二次判断,如果还是不存在,则表明出现了内存泄漏。
ReferenceQueue对象
引用队列,在检测到适当的可到达性更改后,垃圾回收器将已注册的引用对象添加到该队列中。就是当一个对象被回收时,会把引用对象放入到ReferenceQueue中,内部是一个链表队列。
1. install
LeakCanary在使用上会调用install方法在application注册,从install开始入手。
分四部:
- refWatcher()
创建一个AndroidRefWatcherBuilder对象,建造者模式的Builder对象,为了创建AndroidRefWatcher对象。AndroidRefWatcher 属于观察者对象。 - listenerServiceClass()
- excludedRefs()
- buildAndInstall() 构造AndroidRefWatcher对象,注册activity的销毁监听,创建弱引用包装要回收的对象,检测是否被回收,如果始终无法回收,产生分析文件和日志。
@NonNull
public static RefWatcher install(@NonNull Application application) {
return ((AndroidRefWatcherBuilder)refWatcher(application)
.listenerServiceClass(DisplayLeakService.class)
.excludedRefs(AndroidExcludedRefs.createAppDefaults().build()))
.buildAndInstall();
}
2.refWatcher
@NonNull
public static AndroidRefWatcherBuilder refWatcher(@NonNull Context context) {
return new AndroidRefWatcherBuilder(context);
}
AndroidRefWatcherBuilder(@NonNull Context context) {
this.context = context.getApplicationContext();
}
3.listenerServiceClass
在调用listenerServiceClass方法的时候传入了一个DisplayLeakService.class。
最后调用了heapDumpListener监听器,字母意思是堆存贮监听器,同时接收了一个ServiceHeapDumpListener实例对象。同时接收外部的DisplayLeakService对象。
@NonNull
public AndroidRefWatcherBuilder listenerServiceClass(@NonNull Class<? extends AbstractAnalysisResultService> listenerServiceClass) {
return (AndroidRefWatcherBuilder)this.heapDumpListener(new ServiceHeapDumpListener(this.context, listenerServiceClass));
}
DisplayLeakService
public class DisplayLeakService extends AbstractAnalysisResultService {
public DisplayLeakService() {
}
protected final void onHeapAnalyzed(@NonNull AnalyzedHeap analyzedHeap) {}
}
ServiceHeapDumpListener
public final class ServiceHeapDumpListener implements Listener {
private final Context context;
private final Class<? extends AbstractAnalysisResultService> listenerServiceClass;
public ServiceHeapDumpListener(@NonNull Context context, @NonNull Class<? extends AbstractAnalysisResultService> listenerServiceClass) {
this.listenerServiceClass = (Class)Preconditions.checkNotNull(listenerServiceClass, "listenerServiceClass");
this.context = ((Context)Preconditions.checkNotNull(context, "context")).getApplicationContext();
}
public void analyze(@NonNull HeapDump heapDump) {
Preconditions.checkNotNull(heapDump, "heapDump");
HeapAnalyzerService.runAnalysis(this.context, heapDump, this.listenerServiceClass);
}
}
4.excludedRefs
执行excludedRefs方法传入了AndroidExcludedRefs.createAppDefaults().build()。AndroidExcludedRefs系统的内存泄漏的默认配置对象。为了把系统的泄漏忽略掉。
//内部类
public static final class Builder {
File heapDumpFile; //堆信息文件
String referenceKey; //key 引用
String referenceName;//引用的name
ExcludedRefs excludedRefs;//系统的内存泄漏的引用对象
long watchDurationMs; //监听 的时间
long gcDurationMs;// gc的时间
long heapDumpDurationMs;
boolean computeRetainedHeapSize;
List<Class<? extends Inspector>> reachabilityInspectorClasses;
}
private final Builder heapDumpBuilder = new Builder();
public final T excludedRefs(ExcludedRefs excludedRefs) {
this.heapDumpBuilder.excludedRefs(excludedRefs);
return this.self();
}
5.buildAndInstall
返回了RefWatcher,其实就是AndroidRefWatcher对象。此处是建造者模式的build方法,创建对象且install。
public RefWatcher buildAndInstall() {
if (LeakCanaryInternals.installedRefWatcher != null) {
throw new UnsupportedOperationException("buildAndInstall() should only be called once.");
} else {
//此处创建观察者对象
RefWatcher refWatcher = this.build();
if (refWatcher != RefWatcher.DISABLED) {
LeakCanaryInternals.setEnabledAsync(this.context, DisplayLeakActivity.class, true);
if (this.watchActivities) {
//执行activity的观察逻辑
ActivityRefWatcher.install(this.context, refWatcher);
}
//如果有fragment的配置,也执行fragment的观察逻辑
if (this.watchFragments) {
Helper.install(this.context, refWatcher);
}
}
LeakCanaryInternals.installedRefWatcher = refWatcher;
return refWatcher;
}
}