欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  科技

LeakCanary 如何实现对内存泄露的监控?

程序员文章站 2022-03-28 18:25:25
一、Activity 生命周期回调方法 LifecycleCallbacks在 Application 中注册 ActivityLifecycleCallbacks 时,可以监听到每个 Activity 的生命周期方法的执行。当 Activity 被销毁时,会回调到 onActivityDestroyed 方法,此时便是 LeakCanary 开始检测 Activity 是否泄露的时机。LeakCanary 通过 RefWatcher.watch(activity) 方法,判断刚刚调用了 onDestro...

一、Activity 生命周期回调方法 LifecycleCallbacks

Application 中注册 ActivityLifecycleCallbacks 时,可以监听到每个 Activity 的生命周期方法的执行。当 Activity 被销毁时,会回调到 onActivityDestroyed 方法,此时便是 LeakCanary 开始检测 Activity 是否泄露的时机。LeakCanary 通过 RefWatcher.watch(activity) 方法,判断刚刚调用了 onDestroy 方法的 Activity 是否泄露了。

二、弱引用 - WeakReference

WeakReference 继承自 Reference,其构造函数如下所示,每个 WeakReference 都会关联一个 ReferenceQueue,当 WeakReference 所指向的对象被 GC 后,这个 WeakReference 对象都会被放入与之相关联的 ReferenceQueue 中。

public abstract class Reference<T> {
	final ReferenceQueue<? super T> queue;
    Reference(T referent, ReferenceQueue<? super T> queue) {
        this.referent = referent;
        this.queue = queue;
    }
}

监控 Activity 是否泄露的逻辑

Activity 调用 onDestroy 方法后,理论上,接下来他应该被回收,这时指向 Activity 的弱引用应该被放入 ReferenceQueue 队列中,这时 ReferenceQueue 不应该为空,如果为空,说明 Activity 还没有被回收,发生了泄露。为了避免由于 gc 不及时带来的误判,LeakCanary 会进行一次手动 gc,代码如下所示

com/squareup/leakcanary/RefWatcher.java

	// 先清空 ReferenceQueue
    removeWeaklyReachableReferences();
    
	// 如果此时 activity 不可达了,说明已经被成功回收,没有泄露
    if (gone(reference) || debuggerControl.isDebuggerAttached()) {
      return;
    }
	// 手动 gc 
    gcTrigger.runGc();

	// 再次清空 ReferenceQueue 
    removeWeaklyReachableReferences();

	// 如果此时 activity 仍然可达,说明发生了 泄露,接下来会导出 heapDump 文件进行分析
	if (!gone(reference)) {
		...
	}

判断是否泄露的时机

IdleHandler 会在 UI 线程的 MessageQueue 为空时调用,由下面代码可知,会在主线程空闲时,5秒后派发一个判断是否泄露的任务 给 后台线程。

public final class AndroidWatchExecutor implements Executor {

	private static final int DELAY_MILLIS = 5000;
    //....
    private void executeDelayedAfterIdleUnsafe(final Runnable runnable) {
        // This needs to be called from the main thread.
        Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() {
          @Override public boolean queueIdle() {
            backgroundHandler.postDelayed(runnable, DELAY_MILLIS);
            return false;
          }
        });
      }
  }

总结

LeakCanary 在 Activity 执行 onDestroy 后,利用 WeakReference 指向的对象被 GC 回收后会放入 ReferenceQueue 的特性,在后台线程中检测 Activity 是否泄露。当检测到泄露时,通过 AndroidHeapDumperdumpHeap 方法导出应用的栈信息到本地磁盘,然后在运行在私有进程:leakcanary 下的 HeapAnalyzerService 组件中对栈信息进行分析,找到泄露的引用和调用轨迹,最后把分析结果发送到通知栏,告知开发者存在内存泄漏。

本文地址:https://blog.csdn.net/liangjiu2009/article/details/108567903

相关标签: android