接着上一篇说的源码部分,分析一下这图中核心代码的意思:
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文件。
未完,待续。。。