• 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")
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

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

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

  • 相关阅读:
    如何基于three.js(webgl)引擎架构,实现3D密集架库房,3D档案室(3d机器人取档、机器人盘点、人工查档、设备巡检)
    企业管理论文题目怎么写?
    Mysql之基础概念
    java EE初阶 — synchronized 关键字 - 监视器锁 monitor lock
    探索前端开发新利器:MFSU
    java实现备忘录模式
    radware负载均衡器配置adc
    数据库定时备份linux篇
    Visual Studio 2019安装详解
    beamManagement(三)connected mode DL Beam training
  • 原文地址:https://blog.csdn.net/u012553125/article/details/125376562