Android-LeakCanary原理分析

来源:互联网 发布:mac air换外壳 编辑:程序博客网 时间:2024/06/05 19:13
介绍
LeakCanary项目是为Java&Android开发提供的一个自动检测内存泄漏的工具,现在很多项目都在引入来提高代码质量,减少不必要的内存泄漏。

核心方法流程图


初始化流程
通过以下方法,将内存泄露框架添加到App中。
//在Application中添加内存监控框架LeakCanary.install(this);
添加到App中,实际上就是构造了一个RefWatcher对象,并且设置Activity生命周期的监听。当Activity被销毁的时候,调用内存泄露框架进行监控。
//实现方法public static RefWatcher install(Application application) {  return refWatcher(application).listenerServiceClass(DisplayLeakService.class)        .excludedRefs(AndroidExcludedRefs.createAppDefaults().build())        .buildAndInstall();}//生产AndroidRefWatcherBuilder内存泄露监控对象构造器public static AndroidRefWatcherBuilder refWatcher(Context context) {  return new AndroidRefWatcherBuilder(context);}
在buildAndInstall()方法中,设置Activity生命周期的监听,并监控Acitivty内存泄露
public RefWatcher buildAndInstall() {    //构造器生产RefWatcher对象    RefWatcher refWatcher = build();    if (refWatcher != DISABLED) {      //添加对Activity生命周期的监听      ActivityRefWatcher.install((Application) context, refWatcher);    }    return refWatcher;  }  //ActivityRefWatcher.install()方法实现  public static void install(Application application, RefWatcher refWatcher) {    new ActivityRefWatcher(application, refWatcher).watchActivities();  }  public void watchActivities() {    //注册Application生命周期监听    application.registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {      @Override      public void onActivityCreated(Activity activity, Bundle savedInstanceState) {      }      @Override      public void onActivityStarted(Activity activity) {      }      @Override      public void onActivityResumed(Activity activity) {      }      @Override      public void onActivityPaused(Activity activity) {      }      @Override      public void onActivityStopped(Activity activity) {      }      @Override      public void onActivitySaveInstanceState(Activity activity, Bundle outState) {      }      @Override      public void onActivityDestroyed(Activity activity) {        //Activity.onDestory()回调时,被触发        ActivityRefWatcher.this.onActivityDestroyed(activity);      }    });  }

检查内存泄露
通过调用watch()方法,触发内存泄露检查。
 /**   * 检测提供的(watchedReference)对象,是否存在内存泄露问题   * @param watchedReference 被检测的对象   * @param referenceName 引用名   */  public void watch(Object watchedReference, String referenceName) {    if (this == DISABLED) {      return;    }    //判空    checkNotNull(watchedReference, "watchedReference");    checkNotNull(referenceName, "referenceName");    //开始检测内存泄漏的时间    final long watchStartNanoTime = System.nanoTime();    //生成检测对象的key    String key = UUID.randomUUID().toString();    //保存检测对象的key    retainedKeys.add(key);    //生成弱引用    final KeyedWeakReference reference =        new KeyedWeakReference(watchedReference, key, referenceName, queue);    //异步检测对象是否内存泄露    ensureGoneAsync(watchStartNanoTime, reference);  }  //异步检测对象是否内存泄露  private void ensureGoneAsync(final long watchStartNanoTime, final KeyedWeakReference reference) {    watchExecutor.execute(new Retryable() {      @Override public Retryable.Result run() {        return ensureGone(reference, watchStartNanoTime);      }    });  }  //真正的内存泄露检测方法  Retryable.Result ensureGone(final KeyedWeakReference reference, final long watchStartNanoTime) {    long gcStartNanoTime = System.nanoTime();    long watchDurationMs = NANOSECONDS.toMillis(gcStartNanoTime - watchStartNanoTime);    //清除此时已经到ReferenceQueue中的弱引用    removeWeaklyReachableReferences();    // (1)如果当前检测的对象已经弱可达,那么说明对象已经不会泄漏    if (gone(reference)) {      return DONE;    }    //如果当前检测对象还没有改变其可达状态,GC()    gcTrigger.runGc();    //再次判断对象有没有进入队列    removeWeaklyReachableReferences();    //(2)如果此时还没有检测到入队列,那么有可能这个对象已经泄漏    if (!gone(reference)) {      //进入第二部,dump内存,分析内存快照      //该部分,暂未分析      long startDumpHeap = System.nanoTime();      long gcDurationMs = NANOSECONDS.toMillis(startDumpHeap - gcStartNanoTime);      File heapDumpFile = heapDumper.dumpHeap();      long heapDumpDurationMs = NANOSECONDS.toMillis(System.nanoTime() - startDumpHeap);      //处理分析结果      heapdumpListener.analyze(          new HeapDump(heapDumpFile, reference.key, reference.name, excludedRefs, watchDurationMs,              gcDurationMs, heapDumpDurationMs));    }    return DONE;  }  //判断检测对象,是否已经被释放  private boolean gone(KeyedWeakReference reference) {    return !retainedKeys.contains(reference.key);  }  //如果为弱引用,在对象被释放的时候,就会将对象添加到ReferenceQueue中  //通过调用ReferenceQueue.poll()来将已经释放的对象从map中移除  private void removeWeaklyReachableReferences() {    KeyedWeakReference ref;    while ((ref = (KeyedWeakReference) queue.poll()) != null) {      retainedKeys.remove(ref.key);    }  }

自动检测Activity内存泄露
由于上面的分析可得,在Activity.onDestory()回调的时候,会触发onActivityDestroyed()监听方法,下面是此方法内容
void onActivityDestroyed(Activity activity) {    refWatcher.watch(activity);}
也就是说,在Activity被销毁的时候,会自动检测此Activity是否存在内存泄露问题。

内存泄露框架划分
内存泄露框架存在三个模块,划分结构如下:
  • leakcanary-watcher: 这是一个通用的内存检测器,对外提供一个 RefWatcher#watch(Object watchedReference),可以看出,它不仅能够检测 Activity,还能监测任意常规的 Java Object 的泄漏情况。
  • leakcanary-android: 这个 module 是与 Android 世界的接入点,用来专门监测 Activity 的泄漏情况,内部使用了 application#registerActivityLifecycleCallbacks 方法来监听 onDestory 事件,然后利用 leakcanary-watcher 来进行弱引用+手动 GC 机制进行监控。
  • leakcanary-analyzer: 这个 module 提供了 HeapAnalyzer,用来对 dump 出来的内存进行分析并返回内存分析结果 AnalysisResult,内部包含了泄漏发生的路径等信息供开发者寻找定位。

原创粉丝点击