android LeakCanary原理解析

LeakCanary原理解析

LeakCanary是square公司开源的一个内存泄露检测的开源库。

理论

理论一:
引用分类:

  • 强引用:强引用还存在,垃圾收集器永远不会回收掉被引用的对象。宁愿抛出OOM异常也不会回收。
  • 软引用:(SoftReference)在JVM将要内存不足时,会进行一次GC,这次GC会回收软引用对象。内存充足时,不会回收软引用。
  • 弱引用: (WeakReference)在JVM发生GC时,无论内存是否足够,都会回收弱引用。
  • 虚引用:(PhantomReference)虚引用时极其不稳定,被引用的对象随时被回收。这个引用存在的唯一目的就是在这个对象被收集器回收时收到一个系统通知,被虚引用关联的对象,和其生存时间完全没关系。PhantomReference表示虚引用,需要搭配ReferenceQueue使用,检测对象回收情况。

理论二:
在声明一个WeakReference对象同时,传入一个ReferenceQueue作为构造参数时,那么当 WeakReference 持有的对象被 GC 回收时,JVM 就会把这个弱引用存入与之关联的引用队列之中。

理论三:
ContentProvider会被在应用启动的时候自动初始化。

理论四:熟悉装饰者模式、策略模式。

解析

先看是如何初始化的:
LeakCanary里的清单文件里面有配置provider标签,如下:

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

再看声明的AppWatcherInstaller类,是会伴随app启动自动初始化的。

internal sealed class AppWatcherInstaller : ContentProvider() {

  /**
   * [MainProcess] automatically sets up the LeakCanary code that runs in the main app process.
   */
  internal class MainProcess : AppWatcherInstaller()

  /**
   * When using the `leakcanary-android-process` artifact instead of `leakcanary-android`,
   * [LeakCanaryProcess] automatically sets up the LeakCanary code
   */
  internal class LeakCanaryProcess : AppWatcherInstaller()

  override fun onCreate(): Boolean {
    val application = context!!.applicationContext as Application
    AppWatcher.manualInstall(application)
    return true
  }

}

里面调用了AppWatcher.manualInstall(application)方法来实现具体的初始化操作。看AppWatcher类:

@JvmOverloads
  fun manualInstall(
    application: Application,
    retainedDelayMillis: Long = TimeUnit.SECONDS.toMillis(5),
    watchersToInstall: List<InstallableWatcher> = appDefaultWatchers(application)
  ) {
  	//检测主线程
    checkMainThread()
    //检测是否安装过
    check(!isInstalled) {
      "AppWatcher already installed"
    }
    check(retainedDelayMillis >= 0) {
      "retainedDelayMillis $retainedDelayMillis must be at least 0 ms"
    }
    this.retainedDelayMillis = retainedDelayMillis
    if (application.isDebuggableBuild) {
    //dubug模式安装鲨鱼 见官网介绍
      LogcatSharkLog.install()
    }
    // Requires AppWatcher.objectWatcher to be set
    //延迟加载,会创建InternalLeakCanary的实例
    LeakCanaryDelegate.loadLeakCanary(application)
	//遍历注入对应4种类型的监听
    watchersToInstall.forEach {
      it.install()
    }
  }

其中appDefaultWatchers会拿到默认需要检测的类型:ActivityFragment RootViewService

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

然后看很关键的一句it.install()InstallableWatcher是个接口,来看看4种具体实现类是如何初始化的:
在这里插入图片描述
ActivityWatcher

class ActivityWatcher(
  private val application: Application,
  private val reachabilityWatcher: ReachabilityWatcher
) : InstallableWatcher {

  private val lifecycleCallbacks =
    object : Application.ActivityLifecycleCallbacks by noOpDelegate() {
    //重写了ActivityLifecycleCallbacks方法,在activity销毁的时候加入监听中
      override fun onActivityDestroyed(activity: Activity) {
      //reachabilityWatcher 就是 ObjectWatch
        reachabilityWatcher.expectWeaklyReachable(
          activity, "${activity::class.java.name} received Activity#onDestroy() callback"
        )
      }
    }

  override fun install() {
//就是注册监听了registerActivityLifecycleCallbacks方法
    application.registerActivityLifecycleCallbacks(lifecycleCallbacks)
  }

  override fun uninstall() {
    application.unregisterActivityLifecycleCallbacks(lifecycleCallbacks)
  }
}

对于ActivityWatcher就是注册监听了registerActivityLifecycleCallbacks方法,在activity走onDestroy方法回调的时候,将activity加入ObjectWatch来检测内存泄露。会执行ObjectWatch的expectWeaklyReachable方法。

FragmentAndViewModelWatcher

class FragmentAndViewModelWatcher(
  private val application: Application,
  private val reachabilityWatcher: ReachabilityWatcher
) : InstallableWatcher {
	//这里创建了fragmentDestroyWatchers的集合
  private val fragmentDestroyWatchers: List<(Activity) -> Unit> = run {
    val fragmentDestroyWatchers = mutableListOf<(Activity) -> Unit>()

    if (SDK_INT >= O) {
      fragmentDestroyWatchers.add(
      //添加AndroidOFragmentDestroyWatcher
        AndroidOFragmentDestroyWatcher(reachabilityWatcher)
      )
    }
	//添加AndroidXFragmentDestroyWatcher
    getWatcherIfAvailable(
      ANDROIDX_FRAGMENT_CLASS_NAME,
      ANDROIDX_FRAGMENT_DESTROY_WATCHER_CLASS_NAME,
      reachabilityWatcher
    )?.let {
      fragmentDestroyWatchers.add(it)
    }
	//添加AndroidSupportFragmentDestroyWatcher
    getWatcherIfAvailable(
      ANDROID_SUPPORT_FRAGMENT_CLASS_NAME,
      ANDROID_SUPPORT_FRAGMENT_DESTROY_WATCHER_CLASS_NAME,
      reachabilityWatcher
    )?.let {
      fragmentDestroyWatchers.add(it)
    }
    fragmentDestroyWatchers
  }

  private val lifecycleCallbacks =
    object : Application.ActivityLifecycleCallbacks by noOpDelegate() {
      override fun onActivityCreated(
        activity: Activity,
        savedInstanceState: Bundle?
      ) {
        for (watcher in fragmentDestroyWatchers) {
          watcher(activity)
        }
      }
    }

  override fun install() {
    //这里一样是注册了registerActivityLifecycleCallbacks
    application.registerActivityLifecycleCallbacks(lifecycleCallbacks)
  }

  override fun uninstall() {
    application.unregisterActivityLifecycleCallbacks(lifecycleCallbacks)
  }

  private fun getWatcherIfAvailable(
    fragmentClassName: String,
    watcherClassName: String,
    reachabilityWatcher: ReachabilityWatcher
  ): ((Activity) -> Unit)? {

    return if (classAvailable(fragmentClassName) &&
      classAvailable(watcherClassName)
    ) {
      val watcherConstructor =
        Class.forName(watcherClassName).getDeclaredConstructor(ReachabilityWatcher::class.java)
      @Suppress("UNCHECKED_CAST")
      watcherConstructor.newInstance(reachabilityWatcher) as (Activity) -> Unit
    } else {
      null
    }
  }

  private fun classAvailable(className: String): Boolean {
    return try {
      Class.forName(className)
      true
    } catch (e: Throwable) {
      false
    }
  }

  companion object {
    private const val ANDROIDX_FRAGMENT_CLASS_NAME = "androidx.fragment.app.Fragment"
    private const val ANDROIDX_FRAGMENT_DESTROY_WATCHER_CLASS_NAME =
      "leakcanary.internal.AndroidXFragmentDestroyWatcher"
    @Suppress("VariableNaming", "PropertyName")
    private val ANDROID_SUPPORT_FRAGMENT_CLASS_NAME =
      StringBuilder("android.").append("support.v4.app.Fragment")
        .toString()
    private const val ANDROID_SUPPORT_FRAGMENT_DESTROY_WATCHER_CLASS_NAME =
      "leakcanary.internal.AndroidSupportFragmentDestroyWatcher"
  }
}

总结下来就是将AndroidOFragmentDestroyWatcher、AndroidXFragmentDestroyWatcher、AndroidSupportFragmentDestroyWatcher各种情况创建的fragment加入一个集合中。
然后在onActivityCreated回调中执行 watcher(activity)方法。
这种写法kotlin的高级用法,上面那些***DestroyWatcher是都实现了(Activity) -> Unit接口,而(Activity) -> Unit这个在java中实现是Function1接口,要实现invoke接口,所以这里的watcher(activity)就是调用invoke方法(kotlin的语法太乱了)。
看invoke方法,上面三个都实现了,大同小异就看一个了AndroidXFragmentDestroyWatcher

  override fun invoke(activity: Activity) {
    if (activity is FragmentActivity) {
      val supportFragmentManager = activity.supportFragmentManager
	//注册了registerFragmentLifecycleCallbacks监听
      supportFragmentManager.registerFragmentLifecycleCallbacks(fragmentLifecycleCallbacks, true)
      // 检测 Activity 中的 ViewModel。
      ViewModelClearedWatcher.install(activity, reachabilityWatcher)
    }
  }

内部重写了registerFragmentLifecycleCallbacks回调:

 override fun onFragmentCreated(
      fm: FragmentManager,
      fragment: Fragment,
      savedInstanceState: Bundle?
    ) {
   // 检测 Activity 中的 ViewModel。
      ViewModelClearedWatcher.install(fragment, reachabilityWatcher)
    }

    override fun onFragmentViewDestroyed(
      fm: FragmentManager,
      fragment: Fragment
    ) {
      val view = fragment.view
      if (view != null) {
     // ObjectWatcher 检测
        reachabilityWatcher.expectWeaklyReachable(
          view, "${fragment::class.java.name} received Fragment#onDestroyView() callback " +
          "(references to its views should be cleared to prevent leaks)"
        )
      }
    }

    override fun onFragmentDestroyed(
      fm: FragmentManager,
      fragment: Fragment
    ) {
    //ObjectWatcher 检测
      reachabilityWatcher.expectWeaklyReachable(
        fragment, "${fragment::class.java.name} received Fragment#onDestroy() callback"
      )
    }

同比activity的监控差不多是一样的逻辑。
AndroidXFragmentDestroyWatcher是多了ViewModelClearedWatcher的监听的,如下:

internal class ViewModelClearedWatcher(
  storeOwner: ViewModelStoreOwner,
  private val reachabilityWatcher: ReachabilityWatcher
) : ViewModel() {

  private val viewModelMap: Map<String, ViewModel>?

  init {
    //通过反射,拿到ViewModel的集合
    viewModelMap = try {
      val mMapField = ViewModelStore::class.java.getDeclaredField("mMap")
      mMapField.isAccessible = true
      @Suppress("UNCHECKED_CAST")
      mMapField[storeOwner.viewModelStore] as Map<String, ViewModel>
    } catch (ignored: Exception) {
      null
    }
  }
	//当不再使用此ViewModel并将其销毁时,将调用此方法
  override fun onCleared() {
    viewModelMap?.values?.forEach { viewModel ->
    //清除的时候会加入 检测
      reachabilityWatcher.expectWeaklyReachable(
        viewModel, "${viewModel::class.java.name} received ViewModel#onCleared() callback"
      )
    }
  }

  companion object {
    fun install(
      storeOwner: ViewModelStoreOwner,
      reachabilityWatcher: ReachabilityWatcher
    ) {
      val provider = ViewModelProvider(storeOwner, object : Factory {
        @Suppress("UNCHECKED_CAST")
        override fun <T : ViewModel?> create(modelClass: Class<T>): T =
        //创建ViewModelClearedWatcher 实例
          ViewModelClearedWatcher(storeOwner, reachabilityWatcher) as T
      })
      provider.get(ViewModelClearedWatcher::class.java)
    }
  }
}

大意就是拿到ViewModel,并监听onCleared方法,在回调时候去执行 reachabilityWatcher.expectWeaklyReachable方法,逻辑也是差不多的。

RootViewWatcher

class RootViewWatcher(
  private val reachabilityWatcher: ReachabilityWatcher
) : InstallableWatcher {

  override fun install() {
    if (Build.VERSION.SDK_INT < 19) {
      return
    }
    //这里相当于去拿windom管理的view,然后洗一遍,加入Runnable监听事件
    swapViewManagerGlobalMViews { mViews ->
      object : ArrayList<View>(mViews) {
        override fun add(element: View): Boolean {
          onRootViewAdded(element)
          return super.add(element)
        }
      }
    }
  }

  override fun uninstall() {
    if (Build.VERSION.SDK_INT < 19) {
      return
    }
    swapViewManagerGlobalMViews { mViews ->
      ArrayList(mViews)
    }
  }

  @SuppressLint("PrivateApi")
  @Suppress("FunctionName")
  private fun swapViewManagerGlobalMViews(swap: (ArrayList<View>) -> ArrayList<View>) {
    try {
    //反射去拿WindowManagerGlobal实例
      val windowManagerGlobalClass = Class.forName("android.view.WindowManagerGlobal")
      val windowManagerGlobalInstance =
        windowManagerGlobalClass.getDeclaredMethod("getInstance").invoke(null)

      val mViewsField =
        windowManagerGlobalClass.getDeclaredField("mViews").apply { isAccessible = true }

      @Suppress("UNCHECKED_CAST")
      val mViews = mViewsField[windowManagerGlobalInstance] as ArrayList<View>

      mViewsField[windowManagerGlobalInstance] = swap(mViews)
    } catch (ignored: Throwable) {
      SharkLog.d(ignored) { "Could not watch detached root views" }
    }
  }

  private fun onRootViewAdded(rootView: View) {
  //去监听view的attach变换,去监听。在调用onViewDetachedFromWindow是执行该方法
    rootView.addOnAttachStateChangeListener(object : OnAttachStateChangeListener {
//开启一个Runnable去执行
      val watchDetachedView = Runnable {
      //rootView开启监听
        reachabilityWatcher.expectWeaklyReachable(
          rootView, "${rootView::class.java.name} received View#onDetachedFromWindow() callback"
        )
      }

      override fun onViewAttachedToWindow(v: View) {
        mainHandler.removeCallbacks(watchDetachedView)
      }

      override fun onViewDetachedFromWindow(v: View) {
        mainHandler.post(watchDetachedView)
      }
    })
  }
}

大意就是通过反射拿到window管理的mViews集合,然后遍历然后加了onViewAttachedToWindowonViewDetachedFromWindow监听,在其销毁的时候执行reachabilityWatcher.expectWeaklyReachable方法,跟上面大意是一样的,销毁时候加入监控。
ServiceWatcher

  private fun onServicePreDestroy(
    token: IBinder,
    service: Service
  ) {
  //根据IBinder加入map中
    servicesToBeDestroyed[token] = WeakReference(service)
  }
private fun onServiceDestroyed(token: IBinder) {
    servicesToBeDestroyed.remove(token)?.also { serviceWeakReference ->
      serviceWeakReference.get()?.let { service ->
      //销毁加入监听
        reachabilityWatcher.expectWeaklyReachable(
          service, "${service::class.java.name} received Service#onDestroy() callback"
        )
      }
    }
  }

在调用service调用onstop的时候加入一个集合map中,在其销毁回调的时候加入监听。大意都差不多。

看完四种模型的监控方式,在看主代码ObjectWatcher,都是通过expectWeaklyReachable方法开始的。

  @Synchronized override fun expectWeaklyReachable(
    watchedObject: Any,
    description: String
  ) {
    if (!isEnabled()) {
      return
    }
   //先看这个
    removeWeaklyReachableObjects()
    //生成唯一的id,存入watchedObjects中
    val key = UUID.randomUUID()
      .toString()
    val watchUptimeMillis = clock.uptimeMillis()
    //创建KeyedWeakReference 并且加入引用队列queue,很重要
    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"
    }
	//存入map集合中
    watchedObjects[key] = reference
    //执行Runnable
    checkRetainedExecutor.execute {
      moveToRetained(key)
    }
  }
removeWeaklyReachableObjects()

先看这个方法:还记得前面的原理二吗?这里就是其应用。
WeakReferences会在它们指向的对象变得可达性后立即入队。这是在最终确定或垃圾回收实际发生之前。

//KeyedWeakReference集合,每次监听会生成唯一id的key加入其中
  private val watchedObjects = mutableMapOf<String, KeyedWeakReference>()
//引用队列,被回收了会加入其队列
  private val queue = ReferenceQueue<Any>()
  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) {
      //不为空,说明该对象已经被gc回收了,不需要在监听了,属于正常销毁回收。
        watchedObjects.remove(ref.key)
      }
      //然后继续清理下一个,为null说明没有被gc回收
    } while (ref != null)
  }
checkRetainedExecutor初始化
  retainedDelayMillis: Long = TimeUnit.SECONDS.toMillis(5),
 checkRetainedExecutor = {
      check(isInstalled) {
        "AppWatcher not installed"
      }
      mainHandler.postDelayed(it, retainedDelayMillis)
    },

初始化设置了间隔时间为5s,有足够的时间触发gc,所以后面还会执行removeWeaklyReachableObjects操作。

moveToRetained(key)
  @Synchronized private fun moveToRetained(key: String) {
  	//在检测一篇
    removeWeaklyReachableObjects()
    //根据key取出被检测对象的KeyedWeakReference
    val retainedRef = watchedObjects[key]
    if (retainedRef != null) {
    //不为null就是泄露了
      retainedRef.retainedUptimeMillis = clock.uptimeMillis()
      //这里会执行InternalLeakCanary里面实现OnObjectRetainedListener的回调方法
      onObjectRetainedListeners.forEach { it.onObjectRetained() }
    }
  }
scheduleRetainedObjectCheck
  fun scheduleRetainedObjectCheck() {
    if (this::heapDumpTrigger.isInitialized) {
      heapDumpTrigger.scheduleRetainedObjectCheck()
    }
  }

  fun scheduleRetainedObjectCheck(
    delayMillis: Long = 0L
  ) {
    val checkCurrentlyScheduledAt = checkScheduledAt
    if (checkCurrentlyScheduledAt > 0) {
    //操作中返回
      return
    }
    checkScheduledAt = SystemClock.uptimeMillis() + delayMillis
    backgroundHandler.postDelayed({
      checkScheduledAt = 0
      checkRetainedObjects()
    }, delayMillis)
  }

最终会走checkRetainedObjects方法

checkRetainedObjects
  private fun checkRetainedObjects() {
    val iCanHasHeap = HeapDumpControl.iCanHasHeap()
	...
	...
    val config = configProvider()
    //获取被监测的数量
    var retainedReferenceCount = objectWatcher.retainedObjectCount
    if (retainedReferenceCount > 0) {
    //大于0,手动触发gc
      gcTrigger.runGc()
      retainedReferenceCount = objectWatcher.retainedObjectCount
    }
	//这里会做一大堆是否要进行堆转储的判断
    if (checkRetainedCount(retainedReferenceCount, config.retainedVisibleThreshold)) return
	//返回false继续
    val now = SystemClock.uptimeMillis()
    //获取上次堆转储的时间差
    val elapsedSinceLastDumpMillis = now - lastHeapDumpUptimeMillis
    //小于1分钟间隔,不会再操作。堆转储是消耗性能的操作
    if (elapsedSinceLastDumpMillis < WAIT_BETWEEN_HEAP_DUMPS_MILLIS) {
    //显示之类的
      onRetainInstanceListener.onEvent(DumpHappenedRecently)
      showRetainedCountNotification(
        objectCount = retainedReferenceCount,
        contentText = application.getString(R.string.leak_canary_notification_retained_dump_wait)
      )
      scheduleRetainedObjectCheck(
        delayMillis = WAIT_BETWEEN_HEAP_DUMPS_MILLIS - elapsedSinceLastDumpMillis
      )
      return
    }
    dismissRetainedCountNotification()
    val visibility = if (applicationVisible) "visible" else "not visible"
    //堆转储
    dumpHeap(
      retainedReferenceCount = retainedReferenceCount,
      retry = true,
      reason = "$retainedReferenceCount retained objects, app is $visibility"
    )
  }

dumpHeap
  private fun dumpHeap(
    retainedReferenceCount: Int,
    retry: Boolean,
    reason: String
  ) {
  //保存资源id到内存
    saveResourceIdNamesToMemory()
    //记录时间
    val heapDumpUptimeMillis = SystemClock.uptimeMillis()
    KeyedWeakReference.heapDumpUptimeMillis = heapDumpUptimeMillis
    //执行操作
    when (val heapDumpResult = heapDumper.dumpHeap()) {
    //失败回调
      is NoHeapDump -> {
        if (retry) {
          SharkLog.d { "Failed to dump heap, will retry in $WAIT_AFTER_DUMP_FAILED_MILLIS ms" }
          scheduleRetainedObjectCheck(
            delayMillis = WAIT_AFTER_DUMP_FAILED_MILLIS
          )
        } else {
          SharkLog.d { "Failed to dump heap, will not automatically retry" }
        }
        showRetainedCountNotification(
          objectCount = retainedReferenceCount,
          contentText = application.getString(
            R.string.leak_canary_notification_retained_dump_failed
          )
        )
      }
      //成功回调
      is HeapDump -> {
        lastDisplayedRetainedObjectCount = 0
        //更新时间,1分钟内只会调用一次
        lastHeapDumpUptimeMillis = SystemClock.uptimeMillis()
        //在清理一次
        objectWatcher.clearObjectsWatchedBefore(heapDumpUptimeMillis)
        //HeapAnalyzerService启动service分析
        HeapAnalyzerService.runAnalysis(
          context = application,
          heapDumpFile = heapDumpResult.file,
          heapDumpDurationMillis = heapDumpResult.durationMillis,
          heapDumpReason = reason
        )
      }
    }
  }

这里的heapDumper.dumpHeap()实际调用的是AndroidHeapDumperdumpHeap方法。

dumpHeap
 override fun dumpHeap(): DumpHeapResult {
 //获取将要转储文件位置
    val heapDumpFile = leakDirectoryProvider.newHeapDumpFile() ?: return NoHeapDump

    val waitingForToast = FutureResult<Toast?>()
    showToast(waitingForToast)
	//超时执行NoHeapDump 回调
    if (!waitingForToast.wait(5, SECONDS)) {
      SharkLog.d { "Did not dump heap, too much time waiting for Toast." }
      return NoHeapDump
    }
	...
	通知栏的一些操作
	...
    val toast = waitingForToast.get()

    return try {
      val durationMillis = measureDurationMillis {
      //核心操作,调用原生的堆转储文件
        Debug.dumpHprofData(heapDumpFile.absolutePath)
      }
      if (heapDumpFile.length() == 0L) {
      //失败,还是执行NoHeapDump回调
        SharkLog.d { "Dumped heap file is 0 byte length" }
        NoHeapDump
      } else {
      //执行成功回调
        HeapDump(file = heapDumpFile, durationMillis = durationMillis)
      }
    } catch (e: Exception) {
      SharkLog.d(e) { "Could not dump heap" }
      // Abort heap dump
      //转换过程坑会报io异常
      NoHeapDump
    } finally {
      cancelToast(toast)
      notificationManager.cancel(R.id.leak_canary_notification_dumping_heap)
    }
  }

在回到HeapAnalyzerService.runAnalysis那边进行分析操作

HeapAnalyzerService.runAnalysis

这个类继承了ForegroundService,而这个是一个IntentService类型的,会执行完自动关闭。
所以会执行onHandleIntent方法,从而走到onHandleIntentInForeground方法。

  override fun onHandleIntentInForeground(intent: Intent?) {
    if (intent == null || !intent.hasExtra(HEAPDUMP_FILE_EXTRA)) {
      SharkLog.d { "HeapAnalyzerService received a null or empty intent, ignoring." }
      return
    }

    // Since we're running in the main process we should be careful not to impact it.
    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND)
    val heapDumpFile = intent.getSerializableExtra(HEAPDUMP_FILE_EXTRA) as File
    val heapDumpReason = intent.getStringExtra(HEAPDUMP_REASON_EXTRA)
    val heapDumpDurationMillis = intent.getLongExtra(HEAPDUMP_DURATION_MILLIS_EXTRA, -1)

    val config = LeakCanary.config
    val heapAnalysis = if (heapDumpFile.exists()) {
      analyzeHeap(heapDumpFile, config)
    } else {
      missingFileFailure(heapDumpFile)
    }
    val fullHeapAnalysis = when (heapAnalysis) {
      is HeapAnalysisSuccess -> heapAnalysis.copy(
        dumpDurationMillis = heapDumpDurationMillis,
        metadata = heapAnalysis.metadata + ("Heap dump reason" to heapDumpReason)
      )
      is HeapAnalysisFailure -> heapAnalysis.copy(dumpDurationMillis = heapDumpDurationMillis)
    }
    onAnalysisProgress(REPORTING_HEAP_ANALYSIS)
    config.onHeapAnalyzedListener.onHeapAnalyzed(fullHeapAnalysis)
  }

会调用analyzeHeap方法,HeapAnalyzer是用于分析堆内存的,再走到heapAnalyzer.analyze方法里面

heapAnalyzer.analyze
 fun analyze(
    heapDumpFile: File,
    leakingObjectFinder: LeakingObjectFinder,
    referenceMatchers: List<ReferenceMatcher> = emptyList(),
    computeRetainedHeapSize: Boolean = false,
    objectInspectors: List<ObjectInspector> = emptyList(),
    metadataExtractor: MetadataExtractor = MetadataExtractor.NO_OP,
    proguardMapping: ProguardMapping? = null
  ): HeapAnalysis {
    val analysisStartNanoTime = System.nanoTime()
	...
	...
    return try {
    //监听状态回调
      listener.onAnalysisProgress(PARSING_HEAP_DUMP)
      //打开io操作
      val sourceProvider = ConstantMemoryMetricsDualSourceProvider(FileSourceProvider(heapDumpFile))
      //打开堆栈图
      sourceProvider.openHeapGraph(proguardMapping).use { graph ->
      //创建FindLeakInput 
        val helpers =
          FindLeakInput(graph, referenceMatchers, computeRetainedHeapSize, objectInspectors)
          //调用analyzeGraph分析
        val result = helpers.analyzeGraph(
          metadataExtractor, leakingObjectFinder, heapDumpFile, analysisStartNanoTime
        )
        val lruCacheStats = (graph as HprofHeapGraph).lruCacheStats()
        val randomAccessStats =
          "RandomAccess[" +
            "bytes=${sourceProvider.randomAccessByteReads}," +
            "reads=${sourceProvider.randomAccessReadCount}," +
            "travel=${sourceProvider.randomAccessByteTravel}," +
            "range=${sourceProvider.byteTravelRange}," +
            "size=${heapDumpFile.length()}" +
            "]"
        val stats = "$lruCacheStats $randomAccessStats"
        result.copy(metadata = result.metadata + ("Stats" to stats))
      }
    } catch (exception: Throwable) {
     ...
     ...
      )
    }
  }
  private fun FindLeakInput.analyzeGraph(
    metadataExtractor: MetadataExtractor,
    leakingObjectFinder: LeakingObjectFinder,
    heapDumpFile: File,
    analysisStartNanoTime: Long
  ): HeapAnalysisSuccess {
  //监听回调
    listener.onAnalysisProgress(EXTRACTING_METADATA)
   //提前元数据
    val metadata = metadataExtractor.extractMetadata(graph)
	//最后检测一遍引用计数
    val retainedClearedWeakRefCount = KeyedWeakReferenceFinder.findKeyedWeakReferences(graph)
      .filter { it.isRetained && !it.hasReferent }.count()

    // This should rarely happens, as we generally remove all cleared weak refs right before a heap
    // dump.
    val metadataWithCount = if (retainedClearedWeakRefCount > 0) {
      metadata + ("Count of retained yet cleared" to "$retainedClearedWeakRefCount KeyedWeakReference instances")
    } else {
      metadata
    }
     listener.onAnalysisProgress(FINDING_RETAINED_OBJECTS)
     //通过泄露堆图找到一组泄露对象id
    val leakingObjectIds = leakingObjectFinder.findLeakingObjectIds(graph)
	//再通过id找到gcroot的路径,找到不可达的对象,由于存在多条泄露对象的路径,要多次记录分析
    val (applicationLeaks, libraryLeaks, unreachableObjects) = findLeaks(leakingObjectIds)

    return HeapAnalysisSuccess(
      heapDumpFile = heapDumpFile,
      createdAtTimeMillis = System.currentTimeMillis(),
      analysisDurationMillis = since(analysisStartNanoTime),
      metadata = metadataWithCount,
      applicationLeaks = applicationLeaks,
      libraryLeaks = libraryLeaks,
      unreachableObjects = unreachableObjects
    )
  }

大意就是通过 IntentService 服务来分析 hprof 文件,分析库使用的是 Shark。具体步骤是首选生成 heap graph(对象关系图),在通过我们放入的弱引用对象来确定泄露的对象,再遍历对象关联的路径生成最短路径。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值