hprof文件不仅仅只能排查oom,还能帮助我们排查验证一些奇奇怪怪的问题,下面是仅举了两个比如。期望经过这几个比如能拓宽大家排除crash的思路。

事例一

能够先考虑一下,遇到以下线上偶现的crash你会怎么去排查。

TransactionTooLargeException

Crash排查系列第一篇|利用hprof文件排查线上偶现问题

分析

TransactionTooLargeException是什么

发生在 远程程序调用(remote procedure call), 这个过程中,参数和返回值会以 Parcel存储 Binder 业务缓冲(transaction buffer)中,当参数和返回值过大,会发生该反常。

检查源码

Crash排查系列第一篇|利用hprof文件排查线上偶现问题
这边我们能够发现可能是mState或许mPersistentState太大了,这边体系也有做相应信息的dumpStats

能够发现logcat里有以下信息

Crash排查系列第一篇|利用hprof文件排查线上偶现问题
能够看出是fragment里面保存了太多东西。途径是androidx.lifecycle.BundlableSavedStateRegistry.key 下的android:support:fragments 下的android:support:fragments

检查代码能够知道android:support:fragments 保存的是下面的parcelable

Crash排查系列第一篇|利用hprof文件排查线上偶现问题
经过体系的logcat我们只能知道这个FragmentManagerState的Parcelable保存数据太大了,详细是哪里还需求将parcelable转为FragmentManagerState再经过日志打印出来。

日志打印计划的缺点

为了找到详细哪个目标占用过大,我们先需求把Parcelable转为FragmentManagerState 这一步就比较麻烦了,需求嵌套循环的去打印

解决

既然是检查目标内存占用问题,其实我们能够经过检查hprof文件解决,在补获TransActionsTooLargeException反常一起去dump下当时的hporf文件 再经过hprof文件回捞排查问题。

Crash排查系列第一篇|利用hprof文件排查线上偶现问题

经过回捞回来的hprof文件发现是这个CommunitySubTabModle创建了300多万个目标。(这儿也能够反过来证明打日志还需求操控好嵌套层数和数组大小,否则就是300w个目标的日志打印了)

这边也很容易想到是反解Parcelable的时分出问题了,检查代码改变 ,Parcelable目标确实新增了个两个字段,反解析的时分读了缓存的老内容导致顺序反常了 。

事例二

线上偶现crash 万分之一不到。

Crash排查系列第一篇|利用hprof文件排查线上偶现问题

Crash排查系列第一篇|利用hprof文件排查线上偶现问题

Restore的时分mActivie中的fragment找不到了,而mActive中fragment通常是在destroy时移除,结合调用途的代码猜想很有可能这个时分activity已经被destroy了。 怎么去验证呢。

我们相同经过crash时的hporf的保存和回捞。

调查viewpager2中保存的数据 找到包括crash信息中uuid的viewpager2,找到引用viewpager2的activity,承认确实已经被destroy了 而且这边activity也被泄漏了。

Crash排查系列第一篇|利用hprof文件排查线上偶现问题

Crash排查系列第一篇|利用hprof文件排查线上偶现问题

Crash排查系列第一篇|利用hprof文件排查线上偶现问题

Crash排查系列第一篇|利用hprof文件排查线上偶现问题

找到泄漏处代码

Crash排查系列第一篇|利用hprof文件排查线上偶现问题

hprof回捞流程

现在仅适用于crash后dump。

  1. 安全中心装备 ,安全中心匹配到规矩后进行hprof dump
{
"crashId": "10993293", //crash 渠道crashid 
"matchCrashType": "java.lang.IllegalStateException", //crash类型
"matchMessage": "Fragment no longer exists for key", //crash message  
"matchMethod": "restoreState",//crash method  堆栈上一处匹配即可
"matchClass": "androidx.viewpager2.adapter.FragmentStateAdapter", //crash 类 堆栈上一处匹配即可
"dumpHprof": 1,//hprof dump开关
"crashTag": 0 
}
  1. 完成dump后会产生埋点上报,需求依据crashId手动整理一波userid

  2. 运用文件回捞功能。

  3. 等候回捞成功告诉。