先明确一个概念
new WeakReference(object, ReferenceQueue)
参数说明
object: 任意对象
ReferenceQueue:一个队列 后边简称queue
当object被gc回收后 WeakReference将会加入到ReferenceQueue队列
leakcanary流程(不讲武德):基于1.5.4
1.监听activity生命周期
LeakCanary.install
public static RefWatcher install(Application application) {
return refWatcher(application).listenerServiceClass(DisplayLeakService.class)
.excludedRefs(AndroidExcludedRefs.createAppDefaults().build())
//监听activity生命周期(自己找代码进去看)
.buildAndInstall();
}
复制代码
2.ondestroy后创建一个key加入set集合,再将key和activity包装到KeyedWeakReference对象中(简称ref)
@Override
public void onActivityDestroyed(Activity activity) {
//destroy回调
ActivityRefWatcher.this.onActivityDestroyed(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();
//保存key
retainedKeys.add(key);
//包装成ref
final KeyedWeakReference reference =
new KeyedWeakReference(watchedReference, key, referenceName, queue);
ensureGoneAsync(watchStartNanoTime, reference);
}
复制代码
3.发送一个idle到主线程空闲时执行
private void ensureGoneAsync(final long watchStartNanoTime, final KeyedWeakReference reference) {
watchExecutor.execute(new Retryable() {
@Override public Retryable.Result run() {
return ensureGone(reference, watchStartNanoTime);
}
});
}
//watchExecutor的创建
public AndroidRefWatcherBuilder watchDelay(long delay, TimeUnit unit) {
return watchExecutor(new AndroidWatchExecutor(unit.toMillis(delay)));
}
void waitForIdle(final Retryable retryable, final int failedAttempts) {
//加入idle列表
Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() {
@Override public boolean queueIdle() {
postToBackgroundWithDelay(retryable, failedAttempts);
return false;
}
});
}
void postToBackgroundWithDelay(final Retryable retryable, final int failedAttempts) {
long exponentialBackoffFactor = (long) Math.min(Math.pow(2, failedAttempts), maxBackoffFactor);
long delayMillis = initialDelayMillis * exponentialBackoffFactor;
backgroundHandler.postDelayed(new Runnable() {
@Override public void run() {
//这里回到刚才的run执行ensureGone
Retryable.Result result = retryable.run();
if (result == RETRY) {
postWaitForIdle(retryable, failedAttempts + 1);
}
}
}, delayMillis);
}
复制代码
4.遍历queue中是否有ref,找到就从set集合中删除key(说明对象已经被回收{上边说过:当object被gc回收后 创建的weakReference对象将会加入到queue队列},所以找到说明对象已经被回收成功不存在泄露)
否则,调用系统gc后再重新在queue中找,如果还是没有找到说明可能泄露了,最后打印堆栈
Retryable.Result ensureGone(final KeyedWeakReference reference, final long watchStartNanoTime) {
long gcStartNanoTime = System.nanoTime();
long watchDurationMs = NANOSECONDS.toMillis(gcStartNanoTime - watchStartNanoTime);
//这里检测queue里有没有weakrefrence对象,有说明成功回收了并移除key
removeWeaklyReachableReferences();
if (debuggerControl.isDebuggerAttached()) {
// The debugger can create false leaks.
return RETRY;
}
//这里重新检查key还在不在,如果在说明上边queue里没有weakrefrence对象,也就是对象还没有被回收
if (gone(reference)) {
return DONE;
}
//调用gc
gcTrigger.runGc();
//再重新检测
removeWeaklyReachableReferences();
//key还存在说明queue里没出现weakrefrence对象(可能存在泄露)
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);
heapdumpListener.analyze(
new HeapDump(heapDumpFile, reference.key, reference.name, excludedRefs, watchDurationMs,
gcDurationMs, heapDumpDurationMs));
}
return DONE;
}
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END