LeakCanary 源码分析

作者: 三木仔 | 来源:发表于2019-01-17 11:16 被阅读7次

    LeakCanary是一个检测内存泄漏的工具,使用非常简单。主要用来检测Activity和Fragment内存泄漏,如果发生内存泄漏,直接在用UI显示哪里发生了泄漏并展示对象引用链。

    LeakCanary地址:https://github.com/square/leakcanary

    LeakCanary的使用

    在gradle文件中加入依赖

    debugImplementation   'com.squareup.leakcanary:leakcanary-support-fragment:1.6.3'
    releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.6.3'
     // 如果使用了 support fragment,需要依赖
    debugImplementation 'com.squareup.leakcanary:leakcanary-support-fragment:1.6.3'
    

    在Application中加入

    public class MyApplication extends Application {
        private RefWatcher refWatcher = null;
        @Override
        public void onCreate() {
            super.onCreate();
            if (!LeakCanary.isInAnalyzerProcess(this)) { // 是否在主进程
                refWatcher = LeakCanary.install(this);
            }
        }
    }
    

    如果想监视其他的Object是否内存泄漏了

    refWatcher.watch(Object object)
    

    原理

    在LeakCanary 的 wiki 就简述了基本的原理:

    1. RefWatcher.watch() 为监视的对象创建一个 KeyedWeakReference;
    2. 然后,后台线程会检查引用是否被清除回收了,如果没有就触发GC;
    3. 如果引用还没被清除,则堆内存dump到文件系统,成一个.hprof文件
    4. HeapAnalyzerService运行在另外一个进程,其中内部的HeapAnalyzer 使用HAHA库解析heap dump
    5. 根据reference key,HeapAnalyzer 找到对应的 KeyedWeakReference,定位内存泄露
    6. HeapAnalyzer 可以找出 GC roots 的最短强引用路径,并确定是否是泄露。如果泄漏,建立导致泄露的引用链。
    7. 将泄漏结果(引用链)传给App进程DisplayLeakService,通知展示

    我们主要看的就是LeakCanary.install(this)到底发生了什么?

    在解析流程之前先看下涉及到的几个重要的类:

    在这里插入图片描述
    1. RefWatcher: 核心类,负责管理和提供入口watch(),由AndroidRefWatcherBuilder创建RefWatcher,建造者模式

    2. WatchExecutor: 负责控制执行检测内存泄漏任务

    3. DebuggerControl:判断是否处于debug

    4. GcTrigger:负责触发一次GC

    5. HeapDump:表示指定时刻的堆栈的快照,AndroidHeapDump为子类

    6. HeapDump.Builder: 负责创建HeapDump

    7. HeapDump.Listener:监听器,当发生内存泄漏的时候,会收到消息,需要触发分析AndroidHeapDump任务

    8. ServiceHeapDumpListener:HeapDump.Listener的实现类,当触发分析任务,调用HeapAnalyzerService执行分析任务

    9. HeapAnalyzerService:是一个Android中四大组件之一的Service,运行在独立的进程,负责执行分析任务和UI通知

    10. HeapAnalyzer:在HeapAnalyzerService内部中,是对DumpHeap分析内存泄漏和找出引用链的工具

    11. retainKeys: 是一个Set<String>,保存着当前还没被回收的Reference的key

    12. ReferenceQueue:引用队列,WeakReference可以关联引用队列,当reference被回收时,会被加入到ReferenceQueue,这样我们就可以判断哪些对象没有被回收了

    13. DisplayLeakService:记录泄漏日志和展示通知的Service

    其实,leakCanary的基本原理就是利用ReferenceQueue,在Activity销毁的时候判断对象有没有被加入ReferenceQueue,若没有则说明Activity还在存活,可能存在泄漏。

    GC Root的种类

    java 使用引用链法来判断一个引用是否该被回收,而出发点就是GC Root

    1. 虚拟机栈的对象引用
    2. 本地方法栈的对象引用
    3. 方法区的常量引用
    4. 方法区的静态对象引用

    源码分析

    isInAnalyzerProcess()方法是用来判断当前的进程是否是在分析进程,因为多进程中,每个进程都会创建Application,而我们需要在非LeakCanary的进程中检测。

    // LeakCanary
    public static boolean isInAnalyzerProcess(@NonNull Context context) {
      Boolean isInAnalyzerProcess = LeakCanaryInternals.isInAnalyzerProcess;
      // This only needs to be computed once per process.
      if (isInAnalyzerProcess == null) {
        isInAnalyzerProcess = isInServiceProcess(context, HeapAnalyzerService.class);
        LeakCanaryInternals.isInAnalyzerProcess = isInAnalyzerProcess;
      }
      return isInAnalyzerProcess;
    }
    

    install方法是LeakCanary的总入口

    public static @NonNull RefWatcher install(@NonNull Application application) {
      return refWatcher(application).listenerServiceClass(DisplayLeakService.class)
          .excludedRefs(AndroidExcludedRefs.createAppDefaults().build())
          .buildAndInstall();
    }
    

    这里使用了Build建造者模式,利用AndroidRefWatcherBuilder创建RefWatcher

    我们分成几个部分:

    1. refWatch(application) 创建AndroidRefWatcherBuilder
    2. listenerServiceClass(DisplayLeakService.class) 设置监听内存泄漏和分析结果的 Service
    3. excludedRefs(AndroidExcludedRefs.createAppDefaults().build()) 设置忽略的内存泄漏的错误
    4. buildAndInstall() 初始化AndroidRefWatcher
    1. refWatch(application)
    // LeakCanary
    public static @NonNull AndroidRefWatcherBuilder refWatcher(@NonNull Context context) {
      return new AndroidRefWatcherBuilder(context);
    }
    

    这里只是创建了AndroidRefWatcherBuilder,最后使用Build模式创建AndroidRefWatcher

    2.listenerServiceClass(DisplayLeakService.class)
    // AndroidRefWatcherBuilder 
    public @NonNull AndroidRefWatcherBuilder listenerServiceClass(
        @NonNull Class<? extends AbstractAnalysisResultService> listenerServiceClass) {
      enableDisplayLeakActivity = DisplayLeakService.class.isAssignableFrom(listenerServiceClass); 
      return heapDumpListener(new ServiceHeapDumpListener(context, listenerServiceClass));
    }
    

    创建了heapDumpListener负责heapDump的分析和处理

    isAssignableFrom() 是object方法,
    例如 a.isAssignableFrom(b) 判断a是不是b的父类或接口

    如果listenerServiceClass继承或者是DisplayLeakService,则enableDisplayLeakActiviy为true,表示显示LeakCanary界面

    // ServiceHeapDumpListener 
    public final class ServiceHeapDumpListener implements HeapDump.Listener {
    
      private final Context context;
      private final Class<? extends AbstractAnalysisResultService> listenerServiceClass;
    
      public ServiceHeapDumpListener(@NonNull final Context context,
          @NonNull final Class<? extends AbstractAnalysisResultService> listenerServiceClass) {
        this.listenerServiceClass = checkNotNull(listenerServiceClass, "listenerServiceClass");
        this.context = checkNotNull(context, "context").getApplicationContext();
      }
    
      @Override public void analyze(@NonNull HeapDump heapDump) {
        checkNotNull(heapDump, "heapDump");
        HeapAnalyzerService.runAnalysis(context, heapDump, listenerServiceClass);
      }
    }
    

    这里简单看一下ServiceHeapDumpListener ,主要方法在analyze(),实际上也只是通知了HeapAnalyzerService.runAnalysis()去分析heapDump;

    HeapAnalyzerService是运行在独立进程的Service。它是一个IntentService,执行完一次任务就会终止。

    3. excludedRefs(AndroidExcludedRefs.createAppDefaults().build())

    AndroidExcludedRefs.java类中维护着一系列的特定的内存泄漏类型,在执行内存泄漏和显示的时候也会忽略这些类

    4. buildAndInstall()
    // AndroidRefWatcherBuilder
    public @NonNull RefWatcher buildAndInstall() {
      if (LeakCanaryInternals.installedRefWatcher != null) {
        throw new UnsupportedOperationException("buildAndInstall() should only be called once.");
      }
      RefWatcher refWatcher = build();
      if (refWatcher != DISABLED) {
        if (enableDisplayLeakActivity) {
          LeakCanaryInternals.setEnabledAsync(context, DisplayLeakActivity.class, true);
        }
        if (watchActivities) {
          ActivityRefWatcher.install(context, refWatcher);
        }
        if (watchFragments) {
          FragmentRefWatcher.Helper.install(context, refWatcher);
        }
      }
      LeakCanaryInternals.installedRefWatcher = refWatcher;
      return refWatcher;
    }
    

    这里也主要分成四个部分:
    (1). build() 构建初始化RefWatcher
    (2). LeakCancaryInternals.setEnabledAsync(context, DisplayLeakActivity.class, true) 设置DisplayLeakActivity不显示图标
    (3). ActivityRefWatcher.install(context, refWatcher) 监测Activity
    (4). FragmentRefWatcher.Helper.install(context, refWatcher) 监测Fragment

    (1) build()
    // RefWatcherBuilder
    public final RefWatcher build() {
      if (isDisabled()) {
        return RefWatcher.DISABLED;
      }
      ...
      return new RefWatcher(watchExecutor, debuggerControl, gcTrigger, heapDumper, heapDumpListener,
          heapDumpBuilder);
    }
    

    AndroidRefWatcherBuilder 是 RefWatcherBuilder的子类,build()方法内部负责创建默认的组件。AndroidRefWatcherBuilder 重写了部分默认方法。

    // AndroidRefWatcherBuilder
    @Override protected @NonNull HeapDumper defaultHeapDumper() {
      LeakDirectoryProvider leakDirectoryProvider =
          LeakCanaryInternals.getLeakDirectoryProvider(context);
      // 创建默认的 AndroidHeapDumper
      return new AndroidHeapDumper(context, leakDirectoryProvider);
    }
    
    @Override protected @NonNull DebuggerControl defaultDebuggerControl() {
      // 创建默认的 AndroidDebuggerControl
      return new AndroidDebuggerControl();
    }
    
    @Override protected @NonNull HeapDump.Listener defaultHeapDumpListener() {
      // 创建默认的 ServiceHeapDumpListener
      return new ServiceHeapDumpListener(context, DisplayLeakService.class);
    }
    
    @Override protected @NonNull WatchExecutor defaultWatchExecutor() {
      // 创建默认的 AndroidWatchExecutor
      return new AndroidWatchExecutor(DEFAULT_WATCH_DELAY_MILLIS);
    }
    
    @Override protected @NonNull
    List<Class<? extends Reachability.Inspector>> defaultReachabilityInspectorClasses() {
      // 创建默认的 AndroidReachabilityInspectors
      return AndroidReachabilityInspectors.defaultAndroidInspectors();
    }
    
    (2) LeakCancaryInternals.setEnabledAsync(context, DisplayLeakActivity.class, true)
    // LeakCanaryInternals
    public static void setEnabledAsync(Context context, final Class<?> componentClass,
        final boolean enabled) {
      final Context appContext = context.getApplicationContext();
      AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
        @Override public void run() {
          setEnabledBlocking(appContext, componentClass, enabled);
        }
      });
    }
    

    这里使用了AsyncTask内部的并发线程池 setEnabledBlocking()

    // LeakCanaryInternals
    public static void setEnabledBlocking(Context appContext, Class<?> componentClass, boolean enabled) {
      ComponentName component = new ComponentName(appContext, componentClass);
      PackageManager packageManager = appContext.getPackageManager();
      int newState = enabled ? COMPONENT_ENABLED_STATE_ENABLED : COMPONENT_ENABLED_STATE_DISABLED;
      // 设置是否隐藏应用图标
      packageManager.setComponentEnabledSetting(component, newState, DONT_KILL_APP);
    }
    

    如果设置一个app的mainActivity为COMPONENT_ENABLED_STATE_DISABLED状态,则不会再launcher的程序图标中发现该app。

    这里设置了DisplayLeakActivity在Launcher程序图标不出现

    (3). ActivityRefWatcher.install(context, refWatcher)
    // ActivityRefWatcher
    public static void install(@NonNull Context context, @NonNull RefWatcher refWatcher) {
      Application application = (Application) context.getApplicationContext();
      ActivityRefWatcher activityRefWatcher = new ActivityRefWatcher(application, refWatcher);
      // 监听application里面的Activity的生命周期
      application.registerActivityLifecycleCallbacks(activityRefWatcher.lifecycleCallbacks);
    }
    
    private final Application.ActivityLifecycleCallbacks lifecycleCallbacks =
        new ActivityLifecycleCallbacksAdapter() {
          @Override public void onActivityDestroyed(Activity activity) {
            refWatcher.watch(activity);
          }
        };
    

    这里才是LeakCanary监测Activity的核心,利用ActivityLifecycleCallbacks监听Activity的生命周期,在Activity销毁的时候,onActivityDestroyed调用refWatcher.watch()

    refWatcher.watch()执行了实际的核心工作,暂时先跳过,后续再继续分析refWatcher.watch()

    (4). FragmentRefWatcher.Helper.install(context, refWatcher)
    // FragmentRefWatcher
    final class Helper {
      private static final String SUPPORT_FRAGMENT_REF_WATCHER_CLASS_NAME =
          "com.squareup.leakcanary.internal.SupportFragmentRefWatcher";
    
      public static void install(Context context, RefWatcher refWatcher) {
        List<FragmentRefWatcher> fragmentRefWatchers = new ArrayList<>();
    
        if (SDK_INT >= O) { // 如果大于Anroid 26,需要增加AndroidOFragmentRefWatcher
          fragmentRefWatchers.add(new AndroidOFragmentRefWatcher(refWatcher));
        }
        try {
          // 利用反射添加SupportFragmentRefWatcher
          Class<?> fragmentRefWatcherClass = Class.forName(SUPPORT_FRAGMENT_REF_WATCHER_CLASS_NAME);
          Constructor<?> constructor =
              fragmentRefWatcherClass.getDeclaredConstructor(RefWatcher.class);
          FragmentRefWatcher supportFragmentRefWatcher =
              (FragmentRefWatcher) constructor.newInstance(refWatcher);
          fragmentRefWatchers.add(supportFragmentRefWatcher);
        } catch (Exception ignored) {
        }
    
        if (fragmentRefWatchers.size() == 0) {
          return;
        }
    
        Helper helper = new Helper(fragmentRefWatchers);
    
        Application application = (Application) context.getApplicationContext();
        application.registerActivityLifecycleCallbacks(helper.activityLifecycleCallbacks);
      }
    

    以上部分是添加了FragmentRefWatcher,用来监测Fragment,其中SupportFragmentRefWatcher是在leakcanary-support-fragment包通过反射添加进来,需要在build.gradle添加依赖。

    // AndroidOFragmentRefWatcher
    private final FragmentManager.FragmentLifecycleCallbacks fragmentLifecycleCallbacks =
        new FragmentManager.FragmentLifecycleCallbacks() {
          @Override public void onFragmentViewDestroyed(FragmentManager fm, Fragment fragment) {
            View view = fragment.getView();
            if (view != null) {
              refWatcher.watch(view);
            }
          }
          @Override
          public void onFragmentDestroyed(FragmentManager fm, Fragment fragment) {
            refWatcher.watch(fragment);
          }
        };
    
    @Override public void watchFragments(Activity activity) {
      FragmentManager fragmentManager = activity.getFragmentManager();
      fragmentManager.registerFragmentLifecycleCallbacks(fragmentLifecycleCallbacks, true);
    }
    

    监测Fragment和监测Activity基本是一样的,利用了FragmentLifecycleCallbacks监听Fragment的生命周期,在销毁状态onFragmentViewDestroyed和onFragmentDestroyed分别检测View和Fragment。

    refWatcher.watch(Object)

    无论是检测Activity还是Fragment,或者是其他类型,都是调用refWatcher.watch(Object)

    再看下AnroidRefWatcher重要的组成部分:

    在这里插入图片描述
    public void watch(Object watchedReference) {
        watch(watchedReference, "");
    }
    
    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);//1
      final KeyedWeakReference reference =
          new KeyedWeakReference(watchedReference, key, referenceName, queue);//2
      ensureGoneAsync(watchStartNanoTime, reference);//3
    }
    

    watch()主要的工作:

    1. 为检测的Object创建一个key,并添加进retainedKeys表示Objectha还存活
    2. 为Object创建一个弱应用,关联queue为引用队列
    3. ensureGoneAsync()执行监测任务
    // RefWatcher
    private void ensureGoneAsync(final long watchStartNanoTime, final KeyedWeakReference reference) {
      watchExecutor.execute(new Retryable() {
         @Override public Retryable.Result run() {
           return ensureGone(reference, watchStartNanoTime);
         }
      });
    }
    

    watchExecutor 是AndroidWatchExecutor

    //AndroidWatchExecutor
    public void execute(@NonNull Retryable retryable) {
      if (Looper.getMainLooper().getThread() == Thread.currentThread()) {
        // 在主线程
        waitForIdle(retryable, 0);
      } else {
        // 切换到主线程
        postWaitForIdle(retryable, 0);
      }
    }
    
    private void postWaitForIdle(final Retryable retryable, final int failedAttempts) {
      // 利用Handler切换到主线程
      mainHandler.post(new Runnable() {
        @Override public void run() {
          waitForIdle(retryable, failedAttempts);
        }
      });
    }
    
      private void waitForIdle(final Retryable retryable, final int failedAttempts) {
        // 添加任务到主线程Looper,等待Looper空闲时候执行
        Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() {
          @Override public boolean queueIdle() {
            postToBackgroundWithDelay(retryable, failedAttempts);
            return false;
          }
        });
      }
    
    private void postToBackgroundWithDelay(final Retryable retryable, final int failedAttempts) {
        long exponentialBackoffFactor = (long) Math.min(Math.pow(2, failedAttempts), maxBackoffFactor);
        long delayMillis = initialDelayMillis * exponentialBackoffFactor;
        // backgroudhandler所在的是HandlerThread
        backgroundHandler.postDelayed(new Runnable() {
          @Override public void run() {
            Retryable.Result result = retryable.run();
            if (result == RETRY) {
              postWaitForIdle(retryable, failedAttempts + 1);
            }
          }
        }, delayMillis);
      }
    

    这里利用Looper的IdleHandler,在Looper空闲的时候执行任务。

    简单总结下AndroidWatcherExecutor,等待主线程空闲的时候,在子线程执行ensureGone()

    // RefWatcher
    Retryable.Result ensureGone(final KeyedWeakReference reference, final long watchStartNanoTime) {
      long gcStartNanoTime = System.nanoTime();
      long watchDurationMs = NANOSECONDS.toMillis(gcStartNanoTime - watchStartNanoTime);
    
      // 1. 从retainedKeys移除掉已经被会回收的弱引用的key
      removeWeaklyReachableReferences();
    
     // 2. 如果是debug模式,会继续重试
      if (debuggerControl.isDebuggerAttached()) {
        // The debugger can create false leaks.
        return RETRY;
      }
    
     // 3. 若当前引用不在retainedKeys,说明不存在内存泄漏
      if (gone(reference)) {
        return DONE;
      }
    
     // 4. 触发一次gc
      gcTrigger.runGc();
    
     // 5.再次从retainedKeys移除掉已经被会回收的弱引用的key
    removeWeaklyReachableReferences();
    
      if (!gone(reference)) {
       // 存在内存泄漏
        long startDumpHeap = System.nanoTime();
        long gcDurationMs = NANOSECONDS.toMillis(startDumpHeap - gcStartNanoTime);
       
       // 6. 创建heapDump文件,还没写入
        File heapDumpFile = heapDumper.dumpHeap();
        if (heapDumpFile == RETRY_LATER) {
          // Could not dump the heap.
          return RETRY;
        }
        long heapDumpDurationMs = NANOSECONDS.toMillis(System.nanoTime() - startDumpHeap);
        // 7. 创建heapDump
        HeapDump heapDump = heapDumpBuilder.heapDumpFile(heapDumpFile).referenceKey(reference.key)
            .referenceName(reference.name)
            .watchDurationMs(watchDurationMs)
            .gcDurationMs(gcDurationMs)
            .heapDumpDurationMs(heapDumpDurationMs)
            .build();
        // 8.调用heapdumpListener分析
        heapdumpListener.analyze(heapDump);
      }
      return DONE;
    }
    
    private boolean gone(KeyedWeakReference reference) {
      return !retainedKeys.contains(reference.key);
    }
    
    private void removeWeaklyReachableReferences() {
      KeyedWeakReference ref;
      while ((ref = (KeyedWeakReference) queue.poll()) != null) {
        retainedKeys.remove(ref.key);
      }
    }
    

    上面的注释把流程基本阐述清楚了,基本逻辑是

    1. 利用引用队列移除掉已经回收的对象
    2. 可能因为回收不及时,所以再次gc
    3. 若对象还没被回收,则发生内存泄漏
    4. 创建HeapDump,后台service执行分析任务

    最后看HeapAnalyzerService分析HeapDump

    // HeapAnalyzerService
    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);
    }
    

    这里的listenerServiceClass 就是从最上面传递过来的DisplayLeakService.class,最后他负责记录日志和展示通知。

    runAnalysis() 启动了HeapAnalyzerService,它是一个IntentService运行在独立进程,负责分析HeapDump和显示通知,既然是IntentService,直接看onHandleIntent(),内部又调用了onHandleIntentInForeground()

    protected void onHandleIntentInForeground(@Nullable Intent intent) {
        String listenerClassName = intent.getStringExtra(LISTENER_CLASS_EXTRA); // DisplayLeakService.class
        HeapDump heapDump = (HeapDump) intent.getSerializableExtra(HEAPDUMP_EXTRA);
        // 创建HeapAnalyzer
        HeapAnalyzer heapAnalyzer =
            new HeapAnalyzer(heapDump.excludedRefs, this, heapDump.reachabilityInspectorClasses);
        // HeapAnanlyzer工具分析
        AnalysisResult result = heapAnalyzer.checkForLeak(heapDump.heapDumpFile, heapDump.referenceKey,
            heapDump.computeRetainedHeapSize);
        // 启动DisplayLeakService记录日志和展示通知
        AbstractAnalysisResultService.sendResultToListener(this, listenerClassName, heapDump, result);
      }
    

    HeapAnalyzer 可以找出 GC roots 的最短强引用路径,并确定是否是泄露。如果泄漏,建立导致泄露的引用链。

    // HeapAnalyzer
    public @NonNull AnalysisResult checkForLeak(@NonNull File heapDumpFile,
        @NonNull String referenceKey,
        boolean computeRetainedSize) {
      long analysisStartNanoTime = System.nanoTime();
    
      if (!heapDumpFile.exists()) {
        Exception exception = new IllegalArgumentException("File does not exist: " + heapDumpFile);
        return failure(exception, since(analysisStartNanoTime));
      }
    
      try {
        listener.onProgressUpdate(READING_HEAP_DUMP_FILE);
        //将heap文件封装成MemoryMappedFileBuffer
        HprofBuffer buffer = new MemoryMappedFileBuffer(heapDumpFile);
        //创建hprof解析器,解析hprof文件
        HprofParser parser = new HprofParser(buffer);
        listener.onProgressUpdate(PARSING_HEAP_DUMP);
        Snapshot snapshot = parser.parse();
        listener.onProgressUpdate(DEDUPLICATING_GC_ROOTS);
        // 移除相同GC root
        deduplicateGcRoots(snapshot);
        listener.onProgressUpdate(FINDING_LEAKING_REF);
        // 找出内存泄漏对象
        Instance leakingRef = findLeakingReference(referenceKey, snapshot);
         //检测是否存在泄漏的引用
        if (leakingRef == null) {
          String className = leakingRef.getClassObj().getClassName();
          return noLeak(className, since(analysisStartNanoTime));
        }
         //根据leakingRef寻找引用路径
        return findLeakTrace(analysisStartNanoTime, snapshot, leakingRef, computeRetainedSize);
      } catch (Throwable e) {
        return failure(e, since(analysisStartNanoTime));
      }
    }
    

    再往下就是如何分析HeapDump,不是本文的重点。

    总结:

    在这里插入图片描述
    1. 无论你是监测Activity还是Fragment亦或是其他Object,最后都是RefWatcher.watch(object)
    2. RefWatcher添加监测的引用, 在主线程 idle 后进行一次强制 gc 后再判断该引用是否在引用队列中,否则就可能是内存泄漏
    3. RefWatcher 通过 HeapDumper 创建HeapDump 和 hprof 文件
    4. HeapAnalyzerService的HeapAnalyzer 分析内存泄漏和找出引用链,最后DisplayLeakService通知

    相关文章

      网友评论

        本文标题:LeakCanary 源码分析

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