美文网首页源码分析
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 2.0源码分析与总结

    本文基于LeakCanary 2.0源码分析LeakCanary - 官方地址LeakCanary - GitHu...

  • LeakCanary 原理分析

    本文主要内容 1、Reference 简介 2、LeakCanary 使用 3、LeakCanary 源码分析 L...

  • LeakCanary原理

    一、源码 LeakCanary内存分析模块,独立进程,包名:leakcanary,保持app进程独立。在Appli...

  • leakcanary源码分析

    leakcanary LeakCananry 是 Square 公司开源的一个针对 Android 的内存泄漏检测...

  • LeakCanary源码分析

    前言 最近高产似母猪,闲下来的时候就喜欢找找源码看。昨天看了下LeakCanary,准备来分析一波。 导入 gra...

  • LeakCanary源码分析

    大家好,我是苍王。 以下是我这个系列的相关文章,有兴趣可以参考一下,可以给个喜欢或者关注我的文章。 [Androi...

  • leakcanary源码分析

    在Application中初始化 使用build设计模式,创建RefWatcher对象 设置heap监听 Serv...

  • LeakCanary 源码分析

    使用 LeakCanary 已经有了最新的2.0 版本,可以去获取最新版本https://github.com/s...

  • LeakCanary源码分析

    1 LeakCanary简介 LeakCanary 是 Square 公司的一个开源库。通过它可以在 App 运行...

  • leakcanary源码分析

    写在前面 leakcanary版本是2.4.0 用法很简单, 就不再说了.使用完后, 有几个问题 为何桌面会多出来...

网友评论

    本文标题:LeakCanary 源码分析

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