美文网首页
LeakCanary分析

LeakCanary分析

作者: Allenlll | 来源:发表于2020-10-09 17:37 被阅读0次

WeakReference

被弱引用的对象当gc运行时会被回收
这个构造方法构造的WeakReference,当被弱引用对象被回收后,会把弱引用对象(WeakReference对象)回收到ReferenceQueue中。
public WeakReference(T referent, ReferenceQueue<? super T> q) {
throw new RuntimeException("Stub!");
}

LeakCanary的使用

  1. 在Application的onCreate中
 if(LeakCanary.isInAnalyzerProcess(this)){
            return;
        }
 LeakCanary.install(this);

  1. 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);
  }

  1. 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;
  }

  1. 最终调用了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);
  }


相关文章

网友评论

      本文标题:LeakCanary分析

      本文链接:https://www.haomeiwen.com/subject/tqilpktx.html