梳理Leakcanary源码20230127

背景

  • 2.0版本相对于1.x版本,全部用的kotlin编写
  • 在application类中,不需要install()方法,监听的是content provider的启动即可

启动监听

1、监听ContentProvider的启动即可

<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.squareup.leakcanary.objectwatcher"
    >

  <application>
    <provider
        android:name="leakcanary.internal.MainProcessAppWatcherInstaller"
        android:authorities="${applicationId}.leakcanary-installer"
        android:enabled="@bool/leak_canary_watcher_auto_install"
        android:exported="false"/>
  </application>
</manifest>


internal class MainProcessAppWatcherInstaller : ContentProvider() {
    override fun onCreate(): Boolean {
      val application = context!!.applicationContext as Application
      静默初始化
      AppWatcher.manualInstall(application)
      return true
    }
}

流程分析

1、在AppWatcher类的manualInstall()方法中,调用LeakCanaryDelegate.loadLeakCanary(),初始化它

object AppWatcher {
  fun manualInstall(
    application: Application,
    retainedDelayMillis: Long = TimeUnit.SECONDS.toMillis(5),
    watchersToInstall: List<InstallableWatcher> = appDefaultWatchers(application)
  ) {
    ...
    LeakCanaryDelegate.loadLeakCanary(application)
    这里完成了ActivityWatcher的install()注册
    watchersToInstall.forEach {
      it.install()
    }
    ...
  }
}

2、通过反射实例化对象,并且通过get(null) as (Application)调用它的invoke方法

internal object LeakCanaryDelegate {
  
  @Suppress("UNCHECKED_CAST")
  val loadLeakCanary by lazy {
    try {
       实例化对象
      val leakCanaryListener = Class.forName("leakcanary.internal.InternalLeakCanary")
      leakCanaryListener.getDeclaredField("INSTANCE")
        .get(null) as (Application) -> Unit
    } catch (ignored: Throwable) {
      NoLeakCanary
    }
  }

  object NoLeakCanary : (Application) -> Unit, OnObjectRetainedListener {
    override fun invoke(application: Application) {
    }

    override fun onObjectRetained() {
    }
  }
}
我们创建InternalAppWatcher时init方法就会调用,onAppWatcherInstalled是kotlin中invoke约定的应用可以将invoke函数的lambda表达式赋值给一个变量,
Kotlin的约定有很多种,而比如使用便捷的get操作,以及重载运算符等等,invoke约定也仅仅是一种约定而已;
我们可以把lambda表达式或者函数直接保存在一个变量中,然后就像执行函数一样直接执行这个变量,
这样的变量通常声明的时候都被我们赋值了已经直接定义好的lambda,或者通过成员引用而获取到的函数;
但是别忘了,在面向对象编程中,一个对象在通常情况下都有自己对应的类,那我们能不能定义一个类,
然后通过构造方法来产生一个对象,然后直接执行它呢?这正是invoke约定发挥作用的地方。
我们只需要在一个类中使用operator来修饰invoke函数,这样的类的对象就可以直接像一个保存lambda表达式的变量一样直接调用,而调用后执行的函数就是invoke函数。
我们还有另一种方式来实现可调用的对象,即让类继承自函数类型,然后重写invoke方法。
————————————————
版权声明:本文为CSDN博主「Darksiderl」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u011148116/article/details/106762665/

3、在AppWatcher的构造函数中appDefaultWatchers(application),初始化了几个观察对象

object AppWatcher {
  构造函数
  fun manualInstall(
    application: Application,
    retainedDelayMillis: Long = TimeUnit.SECONDS.toMillis(5),
    watchersToInstall: List<InstallableWatcher> = appDefaultWatchers(application)
  ) {
    ...
    ...
  }
 
  多个观察者
  fun appDefaultWatchers(
    application: Application,
    reachabilityWatcher: ReachabilityWatcher = objectWatcher
  ): List<InstallableWatcher> {
    return listOf(
      ActivityWatcher(application, reachabilityWatcher),
      FragmentAndViewModelWatcher(application, reachabilityWatcher),
      RootViewWatcher(reachabilityWatcher),
      ServiceWatcher(reachabilityWatcher)
    )
  }
}

我们找到其中一个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)
  }
}

4、在onActivityDestroyed触发的时候会调用reachabilityWatcher.expectWeaklyReachable()方法,reachabilityWatcher的类型是ReachabilityWatcher,在构造方法传入

fun appDefaultWatchers(
    application: Application,
    reachabilityWatcher: ReachabilityWatcher = objectWatcher
  ): List<InstallableWatcher> {
    return listOf(
      ActivityWatcher(application, reachabilityWatcher),
      ...
    )
  }

由此可知道reachabilityWatcher是objectWatcher传入的,它是一个ObjectWatcher类型

val objectWatcher = ObjectWatcher(
    clock = { SystemClock.uptimeMillis() },
    checkRetainedExecutor = {
      check(isInstalled) {
        "AppWatcher not installed"
      }
      mainHandler.postDelayed(it, retainedDelayMillis)
    },
    isEnabled = { true }
  )

5、reachabilityWatcher.expectWeaklyReachable()实际调用的就是在ObjectWatcher.expectWeaklyReachable()方法

class ObjectWatcher constructor() : ReachabilityWatcher {
    
 @Synchronized override fun expectWeaklyReachable(
    watchedObject: Any,
    description: String
  ) {
    if (!isEnabled()) {
      return
    }
    removeWeaklyReachableObjects()
    val key = UUID.randomUUID()
      .toString()
    val watchUptimeMillis = clock.uptimeMillis()
    val reference =
      KeyedWeakReference(watchedObject, key, description, watchUptimeMillis, queue)
    SharkLog.d {
      "Watching " +
        (if (watchedObject is Class<*>) watchedObject.toString() else "instance of ${watchedObject.javaClass.name}") +
        (if (description.isNotEmpty()) " ($description)" else "") +
        " with key $key"
    }

    watchedObjects[key] = reference
    checkRetainedExecutor.execute {
      moveToRetained(key)
    }
  }
}

需要了解知识点:gc后,软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。

  • removeWeaklyReachableObjects() 方法这个数据被回收了(不为空),那么从被观察的集合中移除
注意KeyedWeakReference是WeakReference类型,可以传入一个队列监听它是否被回收,参考WeakReference类的定义构造函数
class KeyedWeakReference(
  referent: Any,
  val key: String,
  val description: String,
  val watchUptimeMillis: Long,
  referenceQueue: ReferenceQueue<Any>
) : WeakReference<Any>(
  referent, referenceQueue
) {}
  private fun removeWeaklyReachableObjects() {
    // 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.
    var ref: KeyedWeakReference?
    do {
      ref = queue.poll() as KeyedWeakReference?
      if (ref != null) {
        watchedObjects.remove(ref.key)
      }
    } while (ref != null)
  }
  • moveToRetained(key)做一次gc操作
  @Synchronized private fun moveToRetained(key: String) {
  removeWeaklyReachableObjects()
    val retainedRef = watchedObjects[key]
    if (retainedRef != null) {
      retainedRef.retainedUptimeMillis = clock.uptimeMillis()
      onObjectRetainedListeners.forEach { it.onObjectRetained() }
    }
  }
  
 private val onObjectRetainedListeners = mutableSetOf<OnObjectRetainedListener>()

 @Synchronized fun addOnObjectRetainedListener(listener: OnObjectRetainedListener) {
    onObjectRetainedListeners.add(listener)
  }

6、回到之前AppWatcher注册环节

object AppWatcher {
  fun manualInstall() {
    ...
    LeakCanaryDelegate.loadLeakCanary(application)
    ...
  }
}

在之前实例化InternalLeakCanary后,调用了invoke()方法,

internal object LeakCanaryDelegate {
  
  @Suppress("UNCHECKED_CAST")
  val loadLeakCanary by lazy {
       实例化对象
      val leakCanaryListener = Class.forName("leakcanary.internal.InternalLeakCanary")
      leakCanaryListener.getDeclaredField("INSTANCE")
        .get(null) as (Application) -> Unit
  }

   调用invoke方法
  object NoLeakCanary : (Application) -> Unit, OnObjectRetainedListener {
    override fun invoke(application: Application) {
    }
  }
}

这里完成了OnObjectRetainedListener的注册

internal object InternalLeakCanary : (Application) -> Unit, OnObjectRetainedListener {
    override fun invoke(application: Application) {
    ...
    AppWatcher.objectWatcher.addOnObjectRetainedListener(this)
    ...
    }
}

7、所以我们看InternalLeakCanary类的onObjectRetained()方法

  override fun onObjectRetained() = scheduleRetainedObjectCheck()

  fun scheduleRetainedObjectCheck() {
    if (this::heapDumpTrigger.isInitialized) {
      heapDumpTrigger.scheduleRetainedObjectCheck()
    }
  }

8、在HeapDumpTrigger类的,触发一次gc,并且下次堆栈信息

internal class HeapDumpTrigger() {
  fun scheduleRetainedObjectCheck(
    delayMillis: Long = 0L
  ) {
      ...
      checkRetainedObjects()
      ...
  }

  private fun checkRetainedObjects() {
        ... 
       触发gc
       gcTrigger.runGc()
       ...  
       下载堆栈信息
       dumpHeap()
    }
}

9、dumpHeap()方法中

private fun dumpHeap(
    retainedReferenceCount: Int,
    retry: Boolean,
    reason: String
  ) {
       ...     
        configProvider().heapDumper.dumpHeap(heapDumpFile)
        ...
  }
internal object InternalLeakCanary : (Application) -> Unit, OnObjectRetainedListener {
    override fun invoke(application: Application) {
    ...
     val configProvider = { LeakCanary.config }

      heapDumpTrigger = HeapDumpTrigger(
      application, backgroundHandler, AppWatcher.objectWatcher, gcTrigger,
      configProvider
    )
    ...
    }
}

LeakCanary.config = LeakCanary.config.copy(dumpHeap = LeakCanary.config.dumpHeap)

object LeakCanary {
 /**
   * The current LeakCanary configuration. Can be updated at any time, usually by replacing it with
   * a mutated copy, e.g.:
   *
   * ```kotlin
   * LeakCanary.config = LeakCanary.config.copy(retainedVisibleThreshold = 3)
   * ```
   *
   * In Java, use [LeakCanary.Config.Builder] instead:
   * ```java
   * LeakCanary.Config config = LeakCanary.getConfig().newBuilder()
   *    .retainedVisibleThreshold(3)
   *    .build();
   * LeakCanary.setConfig(config);
   * ```
   */
  @JvmStatic @Volatile
  var config: Config = Config()
    set(newConfig) {
      val previousConfig = field
      field = newConfig
      HeapDumpControl.updateICanHasHeapInBackground()
    }
  
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容