美文网首页源码分析
LeakCanary 源码分析

LeakCanary 源码分析

作者: h2coder | 来源:发表于2022-04-29 23:57 被阅读0次

    前言

    本篇LeakCanary源码分析,基于1.6.3版本,使用Java编写,而不是最新的2.x版本。

    2.x版本使用Kotlin语言重写,1.x需要在代码中进行手动安装LeakCanary2.x版本则是通过ContentProvider进行自动安装。

    简单使用

    • 添加依赖
    dependencies {
        debugCompile 'com.squareup.leakcanary:leakcanary-android:1.6.3'
        releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.6.3'
    }
    
    • 安装LeakCanary
    public class ExampleApplication extends Application {
        @Override
        public void onCreate() {
            super.onCreate();
            if (LeakCanary.isInAnalyzerProcess(this)) {
                // This process is dedicated to LeakCanary for heap analysis.
                // You should not init your app in this process.
                return;
            }
            LeakCanary.install(this);
        }
    }
    
    • 运行App,桌面会生成多一个LeakCanary的图标入口,当可能存在内存泄漏时,App页面会Toast提醒,并开始分析堆内存,分析完毕会发送一个通知,点击通知跳转到分析详情页,我们按照内存泄漏的链路,查找问题点修复即可,非常方便

    源码分析

    LeakCanary.install 安装

    LeakCanary.install(),是LeakCanary的入口方法,我们从这个方法开始看起

    • refWatcher(),创建RefWatcherBuilder,使用了构建者Builder模式
    • listenerServiceClass(),设置展示分析结果的前台服务Class
    • excludedRefs(),添加一些需要忽略的对象,例如AOSP中一些泄露的对象
    • buildAndInstall(),开始安装,生成RefWatcher对象
    public final class LeakCanary {
      /**
       * Creates a {@link RefWatcher} that works out of the box, and starts watching activity
       * references (on ICS+).
       * 
       * 安装LeakCanary
       */
      public static @NonNull
      RefWatcher install(@NonNull Application application) {
        return refWatcher(application)
                //设置分析内存泄露和发送结果通知的前台服务
                .listenerServiceClass(DisplayLeakService.class)
                //添加一些需要忽略的对象,例如AOSP中一些泄露的对象
                .excludedRefs(AndroidExcludedRefs.createAppDefaults().build())
                //开始安装
                .buildAndInstall();
      }
      
      /**
       * 创建AndroidRefWatcherBuilder对象
       */
      public static @NonNull AndroidRefWatcherBuilder refWatcher(@NonNull Context context) {
        return new AndroidRefWatcherBuilder(context);
      }
    }
    
    • ActivityRefWatcher监听Activity的内存泄漏
    • FragmentRefWatcher监听Fragment的内存泄漏
    /** A {@link RefWatcherBuilder} with appropriate Android defaults. */
    //AndroidRefWatcherBuilder继承于RefWatcherBuilder,是针对安卓平台使用的
    public final class AndroidRefWatcherBuilder extends RefWatcherBuilder<AndroidRefWatcherBuilder> {
    
      /**
       * 默认内存泄漏监测的开始延时时间
       */
      private static final long DEFAULT_WATCH_DELAY_MILLIS = SECONDS.toMillis(5);
    
      /**
       * Sets a custom {@link AbstractAnalysisResultService} to listen to analysis results. This
       * overrides any call to {@link #heapDumpListener(HeapDump.Listener)}.
       *
       * 设置一个自定义的AbstractAnalysisResultService子类,用于分析内存泄露,并把结果发送到通知中
       */
      public @NonNull AndroidRefWatcherBuilder listenerServiceClass(
          @NonNull Class<? extends AbstractAnalysisResultService> listenerServiceClass) {
        enableDisplayLeakActivity = DisplayLeakService.class.isAssignableFrom(listenerServiceClass);
        return heapDumpListener(new ServiceHeapDumpListener(context, listenerServiceClass));
      }
      
      /**
       * Creates a {@link RefWatcher} instance and makes it available through {@link
       * LeakCanary#installedRefWatcher()}.
       *
       * Also starts watching activity references if {@link #watchActivities(boolean)} was set to true.
       *
       * @throws UnsupportedOperationException if called more than once per Android process.
       */
      public @NonNull RefWatcher buildAndInstall() {
        //不允许重复调用安装方法
        if (LeakCanaryInternals.installedRefWatcher != null) {
          throw new UnsupportedOperationException("buildAndInstall() should only be called once.");
        }
        //创建RefWatcher对象
        RefWatcher refWatcher = build();
        //非禁用状态,进入if
        if (refWatcher != DISABLED) {
          if (enableDisplayLeakActivity) {
            LeakCanaryInternals.setEnabledAsync(context, DisplayLeakActivity.class, true);
          }
          //watchActivities 默认为true,默认允许监听Activity内存泄露
          if (watchActivities) {
            ActivityRefWatcher.install(context, refWatcher);
          }
          //watchFragments 默认为true,默认允许监听Fragment内存泄露
          if (watchFragments) {
            FragmentRefWatcher.Helper.install(context, refWatcher);
          }
        }
        //更新安装完成的标志位
        LeakCanaryInternals.installedRefWatcher = refWatcher;
        return refWatcher;
      }
     }
    }
    

    ActivityRefWatcher

    通过Application注册Activity生命周期回调,在ActivityonDestroy()生命周期方法回调时,通过RefWatcher对Activity对象进行内存泄漏监测

    @SuppressWarnings("DeprecatedIsStillUsed")
    @Deprecated
    public final class ActivityRefWatcher {
    
      public static void installOnIcsPlus(@NonNull Application application,
          @NonNull RefWatcher refWatcher) {
        install(application, refWatcher);
      }
    
      /**
       * 开始监听Activity内存泄露
       */
      public static void install(@NonNull Context context, @NonNull RefWatcher refWatcher) {
        Application application = (Application) context.getApplicationContext();
        //创建监听对象
        ActivityRefWatcher activityRefWatcher = new ActivityRefWatcher(application, refWatcher);
        //开始监听Activity生命周期
        application.registerActivityLifecycleCallbacks(activityRefWatcher.lifecycleCallbacks);
      }
    
      /**
       * Activity生命周期回调对象
       */
      private final Application.ActivityLifecycleCallbacks lifecycleCallbacks =
          new ActivityLifecycleCallbacksAdapter() {
            @Override public void onActivityDestroyed(Activity activity) {
              //Activity的onDestroy()被调用,准备销毁时,开始监听对象是否内存泄露
              refWatcher.watch(activity);
            }
          };
    
      private final Application application;
      private final RefWatcher refWatcher;
    
      /**
       * Activity内存泄露监听器
       */
      private ActivityRefWatcher(Application application, RefWatcher refWatcher) {
        this.application = application;
        this.refWatcher = refWatcher;
      }
    
      /**
       * 开始监听
       */
      public void watchActivities() {
        // Make sure you don't get installed twice.
        //确保只会有一次监听,避免重复注册
        stopWatchingActivities();
        application.registerActivityLifecycleCallbacks(lifecycleCallbacks);
      }
    
      /**
       * 停止监听
       */
      public void stopWatchingActivities() {
        application.unregisterActivityLifecycleCallbacks(lifecycleCallbacks);
      }
    }
    

    FragmentRefWatcher

    FragmentRefWatcher也比较类型,先通过Application监听ActivityonCreate()回调,在回调中获取FragmentManager,注册Fragment的生命周期

    Fragment分android.app.Fragment包下的Fragment,以及Support包的Fragmentandroid.app.Fragment包下的Fragment需要在Android 8.0开始才有FragmentManager监听Fragment生命周期的方法,而Support包的Fragment则直接提供了

    /**
     * Internal class used to watch for fragments leaks.
     */
    public interface FragmentRefWatcher {
    
      /**
       * 监听Activity上Fragment的内存泄露
       */
      void watchFragments(Activity activity);
    
      final class Helper {
    
        private static final String SUPPORT_FRAGMENT_REF_WATCHER_CLASS_NAME =
            "com.squareup.leakcanary.internal.SupportFragmentRefWatcher";
    
        /**
         * 开始监听Fragment内存泄露
         */
        public static void install(Context context, RefWatcher refWatcher) {
          List<FragmentRefWatcher> fragmentRefWatchers = new ArrayList<>();
    
          //Android 8.0,监听android.app.Fragment包下的Fragment
          if (SDK_INT >= O) {
            fragmentRefWatchers.add(new AndroidOFragmentRefWatcher(refWatcher));
          }
    
          //监听Support包的Fragment,具体实现在SupportFragmentRefWatcher中
          try {
            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) {
          }
    
          //android.app.Fragment包、Support包的Fragment,都不能监听,那么return
          if (fragmentRefWatchers.size() == 0) {
            return;
          }
    
          Helper helper = new Helper(fragmentRefWatchers);
          //注册监听Activity的生命周期
          Application application = (Application) context.getApplicationContext();
          application.registerActivityLifecycleCallbacks(helper.activityLifecycleCallbacks);
        }
    
        private final Application.ActivityLifecycleCallbacks activityLifecycleCallbacks =
            new ActivityLifecycleCallbacksAdapter() {
              @Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
                //Activity销毁,监听Fragment内存泄露
                for (FragmentRefWatcher watcher : fragmentRefWatchers) {
                  watcher.watchFragments(activity);
                }
              }
            };
    
        private final List<FragmentRefWatcher> fragmentRefWatchers;
    
        private Helper(List<FragmentRefWatcher> fragmentRefWatchers) {
          this.fragmentRefWatchers = fragmentRefWatchers;
        }
      }
    }
    

    AndroidOFragmentRefWatcher

    /**
     * Android 8.0以上,可监听android.app.Fragment包下的Fragment
     */
    @RequiresApi(Build.VERSION_CODES.O) //
    class AndroidOFragmentRefWatcher implements FragmentRefWatcher {
    
      private final RefWatcher refWatcher;
    
      AndroidOFragmentRefWatcher(RefWatcher refWatcher) {
        this.refWatcher = refWatcher;
      }
    
      private final FragmentManager.FragmentLifecycleCallbacks fragmentLifecycleCallbacks =
          new FragmentManager.FragmentLifecycleCallbacks() {
    
            @Override public void onFragmentViewDestroyed(FragmentManager fm, Fragment fragment) {
              //监听Fragment的View是否内存泄露
              View view = fragment.getView();
              if (view != null) {
                refWatcher.watch(view);
              }
            }
    
            @Override
            public void onFragmentDestroyed(FragmentManager fm, Fragment fragment) {
              //监听Fragment对象是否内存泄露
              refWatcher.watch(fragment);
            }
          };
    
      @Override public void watchFragments(Activity activity) {
        //获取FragmentManager,注册Fragment的生命周期回调
        FragmentManager fragmentManager = activity.getFragmentManager();
        fragmentManager.registerFragmentLifecycleCallbacks(fragmentLifecycleCallbacks, true);
      }
    }
    

    SupportFragmentRefWatcher

    /**
     * 监听Support包的Fragment,该类会被反射创建和调用
     */
    class SupportFragmentRefWatcher implements FragmentRefWatcher {
      private final RefWatcher refWatcher;
    
      SupportFragmentRefWatcher(RefWatcher refWatcher) {
        this.refWatcher = refWatcher;
      }
    
      private final FragmentManager.FragmentLifecycleCallbacks fragmentLifecycleCallbacks =
          new FragmentManager.FragmentLifecycleCallbacks() {
    
            @Override public void onFragmentViewDestroyed(FragmentManager fm, Fragment fragment) {
              //监听Fragment的View是否内存泄露
              View view = fragment.getView();
              if (view != null) {
                refWatcher.watch(view);
              }
            }
    
            @Override public void onFragmentDestroyed(FragmentManager fm, Fragment fragment) {
              //监听Fragment对象是否内存泄露
              refWatcher.watch(fragment);
            }
          };
    
      @Override public void watchFragments(Activity activity) {
        //获取FragmentManager,注册Fragment的生命周期回调
        if (activity instanceof FragmentActivity) {
          FragmentManager supportFragmentManager =
              ((FragmentActivity) activity).getSupportFragmentManager();
          supportFragmentManager.registerFragmentLifecycleCallbacks(fragmentLifecycleCallbacks, true);
        }
      }
    }
    

    RefWatcher

    不难发现,不管是ActivityRefWatcher,还是FragmentRefWatcher,都是通过RefWatcherwatch()方法进行监听对象内存泄漏的,接下来就是分析它

    • 首先,生成一个唯一Key,用于标识泄露的对象,并保存到一个Set集合
    • 创建一个弱引用包裹需要监听内存泄漏的对象,并绑定queue弱引用队列,当弱引用被回收时,会把弱引用放进这个队列中
    • 调用ensureGoneAsync(),开始定时监听对象是否被GC回收
    public final class RefWatcher {
      private final WatchExecutor watchExecutor;
      private final DebuggerControl debuggerControl;
      private final GcTrigger gcTrigger;
      private final HeapDumper heapDumper;
      private final HeapDump.Listener heapdumpListener;
      private final HeapDump.Builder heapDumpBuilder;
      private final Set<String> retainedKeys;
      private final ReferenceQueue<Object> queue;
      
      RefWatcher(WatchExecutor watchExecutor, DebuggerControl debuggerControl, GcTrigger gcTrigger,
          HeapDumper heapDumper, HeapDump.Listener heapdumpListener, HeapDump.Builder heapDumpBuilder) {
        this.watchExecutor = checkNotNull(watchExecutor, "watchExecutor");
        this.debuggerControl = checkNotNull(debuggerControl, "debuggerControl");
        this.gcTrigger = checkNotNull(gcTrigger, "gcTrigger");
        this.heapDumper = checkNotNull(heapDumper, "heapDumper");
        this.heapdumpListener = checkNotNull(heapdumpListener, "heapdumpListener");
        this.heapDumpBuilder = heapDumpBuilder;
        retainedKeys = new CopyOnWriteArraySet<>();
        queue = new ReferenceQueue<>();
      }
    
      /**
       * Identical to {@link #watch(Object, String)} with an empty string reference name.
       *
       * 和watch(object, string)方法相同,只是第二个参数 referenceName 为空字符串
       *
       * @see #watch(Object, String)
       */
      public void watch(Object watchedReference) {
        watch(watchedReference, "");
      }
      
      /**
       * Watches the provided references and checks if it can be GCed. This method is non blocking,
       * the check is done on the {@link WatchExecutor} this {@link RefWatcher} has been constructed
       * with.
       *
       * @param referenceName An logical identifier for the watched object.
       */
      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);
        //创建一个弱引用,并绑定queue弱引用队列
        final KeyedWeakReference reference =
            new KeyedWeakReference(watchedReference, key, referenceName, queue);
    
        //开始定时监听对象是否被GC回收
        ensureGoneAsync(watchStartNanoTime, reference);
      }
    }
    
    • ensureGoneAsync(),通过watchExecutor对象,提交一个任务,任务调用ensureGone()方法
    • 这个watchExecutorAndroidWatchExecutor
    • AndroidWatchExecutor类似线程池,但它使用HandlerThread来执行任务
    • 先使用主线程的Handler,发送一个闲时消息,并在闲时消息中,再使用HandlerThread发送一个5秒延时的消息进行任务,接下来我们回到ensureGone()
    public final class RefWatcher {
      /**
       * 开始定时监听对象是否被GC回收
       * @param watchStartNanoTime 对象开始监听的时间
       * @param reference 要监听的对象
       */
      private void ensureGoneAsync(final long watchStartNanoTime, final KeyedWeakReference reference) {
        //通过线程池发出任务
        watchExecutor.execute(new Retryable() {
          @Override public Result run() {
            //执行任务
            return ensureGone(reference, watchStartNanoTime);
          }
        });
      }
    }
    
    /**
     * A {@link WatchExecutor} is in charge of executing a {@link Retryable} in the future, and retry
     * later if needed.
     *
     * 对象监听任务执行器,还支持任务重试
     */
    public interface WatchExecutor {
      /**
       * 不执行任务的实现
       */
      WatchExecutor NONE = new WatchExecutor() {
        @Override public void execute(Retryable retryable) {
        }
      };
    
      /**
       * 执行任务方法
       *
       * @param retryable 可重试任务
       */
      void execute(Retryable retryable);
    }
    
    public final class AndroidWatchExecutor implements WatchExecutor {
      static final String LEAK_CANARY_THREAD_NAME = "LeakCanary-Heap-Dump";
      private final Handler mainHandler;
      private final Handler backgroundHandler;
      private final long initialDelayMillis;
      private final long maxBackoffFactor;
      
      public AndroidWatchExecutor(long initialDelayMillis) {
        mainHandler = new Handler(Looper.getMainLooper());
        HandlerThread handlerThread = new HandlerThread(LEAK_CANARY_THREAD_NAME);
        handlerThread.start();
        backgroundHandler = new Handler(handlerThread.getLooper());
        this.initialDelayMillis = initialDelayMillis;
        maxBackoffFactor = Long.MAX_VALUE / initialDelayMillis;
      }
    
      @Override public void execute(@NonNull Retryable retryable) {
        //如果是主线程,发送闲时消息来处理任务
        if (Looper.getMainLooper().getThread() == Thread.currentThread()) {
          waitForIdle(retryable, 0);
        } else {
          //非主线程,把任务发到主线程,再重新执行 waitForIdle() 方法
          postWaitForIdle(retryable, 0);
        }
      }
      
      /**
       * 发送闲时消息来执行任务
       *
       * @param retryable 任务
       * @param failedAttempts 重试次数
       */
      private void waitForIdle(final Retryable retryable, final int failedAttempts) {
        // This needs to be called from the main thread.
        //这个方法,必须在主线程调用
        Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() {
          @Override public boolean queueIdle() {
            //闲时消息执行
            postToBackgroundWithDelay(retryable, failedAttempts);
            return false;
          }
        });
      }
      
      /**
       * 确保在主线程中执行任务
       *
       * @param retryable 任务
       * @param failedAttempts 重试次数
       */
      private void postWaitForIdle(final Retryable retryable, final int failedAttempts) {
        mainHandler.post(new Runnable() {
          @Override public void run() {
            waitForIdle(retryable, failedAttempts);
          }
        });
      }
      
      /**
       * 延时指定时间再执行
       *
       * @param retryable 任务
       * @param failedAttempts 重试次数
       */
      private 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() {
            //执行任务
            Retryable.Result result = retryable.run();
            //如果任务结果是重试,那么再发一次闲时消息,再执行一次
            if (result == RETRY) {
              postWaitForIdle(retryable, failedAttempts + 1);
            }
          }
        }, delayMillis);
      }
    }
    
    • 任务执行,先调用removeWeaklyReachableReferences(),通过一个while循环,不断从队列中获取被回收的弱引用对象,如果能获取到,就是有对象被回调,那么把它从Set中移除
    • 调用gone()方法,检查弱引用的Key是否还在Set中,如果不存在就代表已经被GC回收了,任务就结束了,如果还存在,那么继续
    • 调用gcTrigger对象的runGc()方法,该方法会通知JVM进行垃圾回收
    • 通知GC完后,再次调用removeWeaklyReachableReferences(),清理已经被回收掉的弱引用对象的Key
    • 再次调用gone()方法,检查弱引用的Key是否已经被移除,如果被移除,证明没有内存泄漏,任务结束。
    • 如果还是没有被移除,就是发生内存泄漏了,使用HeapDump对象把堆内存Dump下来进行分析
    public final class RefWatcher {
      @SuppressWarnings("ReferenceEquality") // Explicitly checking for named null.
      Retryable.Result ensureGone(final KeyedWeakReference reference, final long watchStartNanoTime) {
        //记录GC开始时间
        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;
        }
    
        //通知一次GC
        gcTrigger.runGc();
        //再次移除已经被回收掉的弱引用对象
        removeWeaklyReachableReferences();
        //再查询一下,这个弱引用对象是否已被回收
        if (!gone(reference)) {//还是没有被回收,可能是对象被内存泄露了
          //记录Dump堆的时间
          long startDumpHeap = System.nanoTime();
          //计算出GC花费的时长
          long gcDurationMs = NANOSECONDS.toMillis(startDumpHeap - gcStartNanoTime);
    
          //执行Dump堆,生成.hprof文件
          File heapDumpFile = heapDumper.dumpHeap();
          //发现Dump失败了,那么再重试
          if (heapDumpFile == RETRY_LATER) {
            // Could not dump the heap.
            return RETRY;
          }
          //Dump成功了,计算花费的时长
          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;
      }
      
      /**
       * 移除已经被回收掉的弱引用对象
       */
      private void removeWeaklyReachableReferences() {
        // WeakReferences are enqueued as soon as the object to which they point to becomes weakly
        // reachable. This is before finalization or garbage collection has actually happened.
        KeyedWeakReference ref;
        //通过一个while循环,不断从队列中获取被回收的弱引用对象,如果能获取到,就是有对象被回调,那么把它从
        while ((ref = (KeyedWeakReference) queue.poll()) != null) {
          retainedKeys.remove(ref.key);
        }
      }
      
      /**
       * 检查弱引用的Key是否还在Set中,如果不存在就代表已经被GC回收了
       *
       * @param reference 要被检查的对象
       * @return true代表对象已被回收
       */
      private boolean gone(KeyedWeakReference reference) {
        return !retainedKeys.contains(reference.key);
      }
    }
    

    GcTrigger

    public interface GcTrigger {
      /**
       * 默认实现
       */
      GcTrigger DEFAULT = new GcTrigger() {
        @Override public void runGc() {
          // Code taken from AOSP FinalizationTest:
          // https://android.googlesource.com/platform/libcore/+/master/support/src/test/java/libcore/
          // java/lang/ref/FinalizationTester.java
          // System.gc() does not garbage collect every time. Runtime.gc() is
          // more likely to perform a gc.
          //如果是 System.gc(),不会每次收到通知都执行GC,而 Runtime.getRuntime().gc(),更有可能执行GC
          Runtime.getRuntime().gc();
          //让线程睡眠一下
          enqueueReferences();
          //通知执行对象的 finalize() 方法
          System.runFinalization();
        }
    
        private void enqueueReferences() {
          // Hack. We don't have a programmatic way to wait for the reference queue daemon to move
          // references to the appropriate queues.
          try {
            Thread.sleep(100);
          } catch (InterruptedException e) {
            throw new AssertionError();
          }
        }
      };
    
      /**
       * 通知执行一次GC
       */
      void runGc();
    }
    

    总结

    LeakCanary的内存泄漏监测方式,是通过对被观察对象通过一个WeakReference弱引用进行包裹,并关联一个ReferenceQueue弱引用队列来监听对象回收。

    然后通过主线程的Handler发送一个闲时消息,在闲时消息中,通过HandlerThread,发送一个延时5秒的消息,开始从弱引用队列中获取对象,如果能获取到对象,则证明被观察对象被回收了。

    如果没有被回收,通知JVM进行GC,再检查一遍弱引用队列,如果获取能到对象,则已被回收,就是没有发生内存泄漏。但如果依旧没有获取到,则发生内存泄漏,开始把堆内存Dump下来,进行分析。

    相关文章

      网友评论

        本文标题:LeakCanary 源码分析

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