LeakCanary 工作原理分析

808 阅读2分钟

版本 2.8.1

初始化

MainProcessAppWatcherInstaller 是一个 ContentProvider, 在应用初始化的过程中创建并调用 onCreate 进行初始化

override fun onCreate(): Boolean {
    val application = context!!.applicationContext as Application
    AppWatcher.manualInstall(application)
    return true
}
// retainedDelayMillis: 存在多长时间算泄漏
// watchersToInstall: 需要安装的 Watchers
fun manualInstall(
    application: Application,
    retainedDelayMillis: Long = TimeUnit.SECONDS.toMillis(5),
    watchersToInstall: List<InstallableWatcher> = appDefaultWatchers(application)
  ) {
    this.retainedDelayMillis = retainedDelayMillis
    // 删除一些检查代码
    LeakCanaryDelegate.loadLeakCanary(application)
    watchersToInstall.forEach {
      it.install()
    }
}
// 默认添加的 Watchers
fun appDefaultWatchers(
    application: Application,
    reachabilityWatcher: ReachabilityWatcher = objectWatcher
  ): List<InstallableWatcher> {
    return listOf(
      ActivityWatcher(application, reachabilityWatcher),
      FragmentAndViewModelWatcher(application, reachabilityWatcher),
      RootViewWatcher(reachabilityWatcher),
      ServiceWatcher(reachabilityWatcher)
    )
}
​
// 注意返回类型是个函数
// 加载 InternalLeakCanary
val loadLeakCanary by lazy {
    try {
      val leakCanaryListener = Class.forName("leakcanary.internal.InternalLeakCanary")
      leakCanaryListener.getDeclaredField("INSTANCE")
        .get(null) as (Application) -> Unit
    } catch (ignored: Throwable) {
      NoLeakCanary
    }
  }
  • 1、保存 retainedDelayMillis
  • 2、获取默认 InstallableWatcher 列表
  • 3、加载 InternalLeakCanary, 后面检测到内存泄漏后dump堆栈用
  • 4、调用对用的 install 方法

InstallableWatchers

前置知识:创建弱引用的时候关联队列引用队列,当对象要被gc回收的时候会先加入到队列中。

eg: ActivityWatcher

class ActivityWatcher(
  private val application: Application,
  private val reachabilityWatcher: ReachabilityWatcher
) : InstallableWatcher {
​
  private val lifecycleCallbacks =
    object : Application.ActivityLifecycleCallbacks by noOpDelegate() {
      override fun onActivityDestroyed(activity: Activity) {
        reachabilityWatcher.expectWeaklyReachable(
          activity, "${activity::class.java.name} received Activity#onDestroy() callback"
        )
      }
    }
​
  override fun install() {
    application.registerActivityLifecycleCallbacks(lifecycleCallbacks)
  }
​
  override fun uninstall() {
    application.unregisterActivityLifecycleCallbacks(lifecycleCallbacks)
  }
}
​
// ObjectWatcher 实例的创建
  val objectWatcher = ObjectWatcher(
    clock = { SystemClock.uptimeMillis() },
    checkRetainedExecutor = {
      check(isInstalled) {
        "AppWatcher not installed"
      }
      mainHandler.postDelayed(it, retainedDelayMillis)
    },
    isEnabled = { true }
  )
​
@Synchronized override fun expectWeaklyReachable(
    watchedObject: Any, // 对应上面的 Activity 实例
    description: String
  ) {
    // 1、移除已经加入引用队列的对象
    removeWeaklyReachableObjects()
    // 2、生成一个 UUID 作为 key
    val key = UUID.randomUUID().toString()
    val watchUptimeMillis = clock.uptimeMillis()
    // 3、创建一个 Activity 的弱引用
    val reference =
      KeyedWeakReference(watchedObject, key, description, watchUptimeMillis, queue)
    
    watchedObjects[key] = reference
    checkRetainedExecutor.execute {
      moveToRetained(key)
    }
  }
​
  private fun removeWeaklyReachableObjects() {
    var ref: KeyedWeakReference?
    do {
      ref = queue.poll() as KeyedWeakReference?
      if (ref != null) {
        // watchedObjects 是一个 map, key 是前面 UUID 生成的, value 的弱引用实例
        watchedObjects.remove(ref.key)
      }
    } while (ref != null)
  }
​
  @Synchronized private fun moveToRetained(key: String) {
    // 在此移除加入引用队列的对象
    removeWeaklyReachableObjects()
    val retainedRef = watchedObjects[key]
    if (retainedRef != null) {
      retainedRef.retainedUptimeMillis = clock.uptimeMillis()
      // 调用 OnObjectRetainedListener 的 onObjectRetained 方法
      onObjectRetainedListeners.forEach { it.onObjectRetained() }
    }
  }
  • 1、内部创建一个 Application.ActivityLifecycleCallbacks 的实现,在 install 的时候进行注册, uninstall 的时候取消注册,
  • 2、在监听到 Activity 销毁的时候, 调用 expectWeaklyReachable 方法,reachabilityWatcherObjectWatcher的一个实例,
  • 3、首先从watchedObjects中移除已经加入引用队列的的对象,其次为当前 Activity 创建一个 KeyedWeakReference 实例,并利用 UUID 生成一个 key,然后添加到 watchedObjects 中去,
  • 4、调用 checkRetainedExecutor.exectue 执行 moveToRetained 方法,
  • 5、从 ObjectWatcher 的构造可以看到 checkRetainedExecutor是一个函数,其中用 Handler 发送了一个延时消息,延时时长就是初始化时传入的参数,默认 5s,
  • 6、moveToRetained 中主要判断当前key对应的 Activity 对象在 onDestroy 5s 之后时候被gc回收了, 如果没有则执行回调 OnObjectRetainedListeneronObjectRetained 方法,
  • 7、根据上面初始化过程执行 InternalLeakCanaryonObjectRetained 获取堆栈信息。