LeakCanary 源码详解(2)

接着上一篇说的源码部分,分析一下这图中核心代码的意思:
在这里插入图片描述moveToRetained方法
在这里插入图片描述然后是onObjectRetained方法
在这里插入图片描述
它其实是在下图的代码中这里添加的

在这里插入图片描述这个方法又指向了scheduleRetainedObjectCheck,你也看到了接着调用了heapDumpTrigger.scheduleRetainedObjectCheck()
在这里插入图片描述,我们看看 heapDumpTrigger.scheduleRetainedObjectCheck(),看看断点的方法 checkRetainedObjects()
在这里插入图片描述重点3个,第一处是调用了gc,第二处,检查残留的object,第三处如果还有残留的,要通知用户,就是报内存泄露提醒
在这里插入图片描述我们看看第三处的细节重点就是 这个PendingIntent,使用 FLAG_IMMUTABLE 标记构建了无法被修改的 PendingIntent。

调用 NotificationManagerCompat.notify() 之后工作就完成了。当系统显示通知,且用户点击通知时,会在我们的 PendingIntent 上调用 PendingIntent.send(),来启动我们的应用的广播,这个时候才会去heap dump ,这有点懒加载到意思吧,哈哈。都是细节。

在这里插入图片描述(sample 中 点击 recreate 按钮的 有一个 checkRetainedObjects scheduleRetainedObjectCheck checkRetainedObjects 循环,不清楚什么用意)

下面图中,我们可以看到在我们点击通知后,看到代码做了什么动作
在这里插入图片描述在这里插入图片描述

 fun onDumpHeapReceived(forceDump: Boolean) {
    
    
    backgroundHandler.post {
    
    
      dismissNoRetainedOnTapNotification()
      gcTrigger.runGc()
      val retainedReferenceCount = objectWatcher.retainedObjectCount
      if (!forceDump && retainedReferenceCount == 0) {
    
    
        SharkLog.d {
    
     "Ignoring user request to dump heap: no retained objects remaining after GC" }
        @Suppress("DEPRECATION")
        val builder = Notification.Builder(application)
          .setContentTitle(
            application.getString(R.string.leak_canary_notification_no_retained_object_title)
          )
          .setContentText(
            application.getString(
              R.string.leak_canary_notification_no_retained_object_content
            )
          )
          .setAutoCancel(true)
          .setContentIntent(NotificationReceiver.pendingIntent(application, CANCEL_NOTIFICATION))
        val notification =
          Notifications.buildNotification(application, builder, LEAKCANARY_LOW)
        notificationManager.notify(
          R.id.leak_canary_notification_no_retained_object_on_tap, notification
        )
        backgroundHandler.postDelayed(
          scheduleDismissNoRetainedOnTapNotification,
          DISMISS_NO_RETAINED_OBJECT_NOTIFICATION_MILLIS
        )
        lastDisplayedRetainedObjectCount = 0
        return@post
      }

      SharkLog.d {
    
     "Dumping the heap because user requested it" }
      dumpHeap(retainedReferenceCount, retry = false, "user request")
    }

重点在最后一行 dumpheap 真正开始收集hprof文件了。

Heap Dump也叫堆转储文件,是一个Java进程在某个时间点上的内存快照。Heap Dump是有着多种类型的。不过总体上heap dump在触发快照的时候都保存了java对象和类的信息。通常在写heap dump文件前会触发一次FullGC,所以heap dump文件中保存的是FullGC后留下的对象信息。
在这里插入图片描述最后我们找到真正做事的是Debug去取的hprof文件。
在这里插入图片描述
未完,待续。。。

猜你喜欢

转载自blog.csdn.net/u012553125/article/details/125376562