WeakReference
被弱引用的对象当gc运行时会被回收
这个构造方法构造的WeakReference,当被弱引用对象被回收后,会把弱引用对象(WeakReference对象)回收到ReferenceQueue中。
public WeakReference(T referent, ReferenceQueue<? super T> q) {
throw new RuntimeException("Stub!");
}
LeakCanary的使用
- 在Application的onCreate中
if(LeakCanary.isInAnalyzerProcess(this)){
return;
}
LeakCanary.install(this);
- install方法
其中DisplayLeakService是展示的逻辑,excludedRefs是设置了可以被忽略的泄露。buildAndInstall是AndroidRefWatcherBuilder的方法,
public static @NonNull RefWatcher install(@NonNull Application application) {
return refWatcher(application).listenerServiceClass(DisplayLeakService.class)
.excludedRefs(AndroidExcludedRefs.createAppDefaults().build())
.buildAndInstall();
}
3、buildAndInstall
ActivityRefWatcher.install(context, refWatcher)是Activity的监听方法
FragmentRefWatcher.Helper.install(context, refWatcher)是Fragment泄露的监听,需要引用 leakcanary-support-fragment dependency
public @NonNull RefWatcher buildAndInstall() {
if (LeakCanaryInternals.installedRefWatcher != null) {
throw new UnsupportedOperationException("buildAndInstall() should only be called once.");
}
RefWatcher refWatcher = build();
if (refWatcher != DISABLED) {
LeakCanaryInternals.setEnabledAsync(context, DisplayLeakActivity.class, true);
if (watchActivities) {
ActivityRefWatcher.install(context, refWatcher);
}
if (watchFragments) {
FragmentRefWatcher.Helper.install(context, refWatcher);
}
}
LeakCanaryInternals.installedRefWatcher = refWatcher;
return refWatcher;
}
4、ActivityRefWatcher的install()
ActivityRefWatcher的install方法就是注册了Activity生命周期的监听
public static void install(@NonNull Context context, @NonNull RefWatcher refWatcher) {
Application application = (Application) context.getApplicationContext();
ActivityRefWatcher activityRefWatcher = new ActivityRefWatcher(application, refWatcher);
application.registerActivityLifecycleCallbacks(activityRefWatcher.lifecycleCallbacks);
}
其中activityRefWatcher.lifecycleCallbacks,在Activity的onDestroy时会调用RefWatcher的watch方法
private final Application.ActivityLifecycleCallbacks lifecycleCallbacks =
new ActivityLifecycleCallbacksAdapter() {
@Override public void onActivityDestroyed(Activity activity) {
refWatcher.watch(activity);
}
};
watch方法,构造一个含有key和name的Activity弱引用对象,然后开始异步监听activity对象是否泄露。
public void watch(Object watchedReference, String referenceName) {
if (this == DISABLED) {
return;
}
checkNotNull(watchedReference, "watchedReference");
checkNotNull(referenceName, "referenceName");
final long watchStartNanoTime = System.nanoTime();
String key = UUID.randomUUID().toString();
retainedKeys.add(key);
final KeyedWeakReference reference =
new KeyedWeakReference(watchedReference, key, referenceName, queue);
ensureGoneAsync(watchStartNanoTime, reference);
}
- removeWeaklyReachableReferences();如果activity对象已经被回收,移除retainedKeys中key和ReferenceQueue中弱引用对象,注册区别,弱引用对象是指构造的KeyedWeakReference而Activity是被弱引用引用的对象。ReferenceQueue中保存的是弱引用对象而不是被回收的Activity。
gone方法判断是否activity已经被回收,如果没有则触发 gc,再次移除,再判断如果没有被回收,则是内存泄露了。导出heapDump文件,然后通过heapdumpListener分析heapDump对象。
Retryable.Result ensureGone(final KeyedWeakReference reference, final long watchStartNanoTime) {
long gcStartNanoTime = System.nanoTime();
long watchDurationMs = NANOSECONDS.toMillis(gcStartNanoTime - watchStartNanoTime);
removeWeaklyReachableReferences();
if (debuggerControl.isDebuggerAttached()) {
// The debugger can create false leaks.
return RETRY;
}
if (gone(reference)) {
return DONE;
}
gcTrigger.runGc();
removeWeaklyReachableReferences();
if (!gone(reference)) {
long startDumpHeap = System.nanoTime();
long gcDurationMs = NANOSECONDS.toMillis(startDumpHeap - gcStartNanoTime);
File heapDumpFile = heapDumper.dumpHeap();
if (heapDumpFile == RETRY_LATER) {
// Could not dump the heap.
return RETRY;
}
long heapDumpDurationMs = NANOSECONDS.toMillis(System.nanoTime() - startDumpHeap);
HeapDump heapDump = heapDumpBuilder.heapDumpFile(heapDumpFile).referenceKey(reference.key)
.referenceName(reference.name)
.watchDurationMs(watchDurationMs)
.gcDurationMs(gcDurationMs)
.heapDumpDurationMs(heapDumpDurationMs)
.build();
heapdumpListener.analyze(heapDump);
}
return DONE;
}
- 最终调用了HeapAnalyzerService的runAnalysis开始分析内存泄露然后通过DisplayLeakService展示
public static void runAnalysis(Context context, HeapDump heapDump,
Class<? extends AbstractAnalysisResultService> listenerServiceClass) {
setEnabledBlocking(context, HeapAnalyzerService.class, true);
setEnabledBlocking(context, listenerServiceClass, true);
Intent intent = new Intent(context, HeapAnalyzerService.class);
intent.putExtra(LISTENER_CLASS_EXTRA, listenerServiceClass.getName());
intent.putExtra(HEAPDUMP_EXTRA, heapDump);
ContextCompat.startForegroundService(context, intent);
}
网友评论