图 6. Shark VS MAT
我们在相同客户端环境对 160M 的 HPROF 多次分析对比发现 MAT 分析速度明显优于 Shark,另外针对 MAT 分析后仍持有统治者树占用内存我们也做了主动释放,对比性能收益后采用基于 MAT 库的分析引擎进行分析,对内存泄漏引用链路自动归并、大对象小对象引用链自动分析、大图线下自动还原线上过滤无用链路,分析结果如下:
内存泄漏
图 7. 内存泄漏链路
对泄漏的 Activity 的引用链进行了聚合分析,方便一次性解决该 Activity 的泄漏链释放内存。
大对象
图 8. 大对象链路
大对象不止分析了引用链路,还递归分析了内部 top 持有对象(InRefrenrece
)的 RetainedSize。
小对象
图 9. 小对象链路
小对象我们对 top 的外部持有对象(OutRefrenrece
)进行聚合得到占有小对象最多的链路。
图片
图 10. 图片链路
图片我们过滤了图片库等无效引用且对 Android 8.0 以下的大图在线下进行了还原。
回传分析
为了最大限度的节省用户流量且规避隐私风险,我们通过自研 HPROF 裁剪工具 Tailor 在 dump 过程对 HPROF 进行了裁剪。
裁剪过程
图 11. Tailor 裁剪流程
去除了无用信息
-
跳过 header
-
分 tag 裁剪
-
裁剪无用信息:char[]; byte[]; timestamp; stack trace serial number; class serial number;
-
压缩数据信息
同时对数据进行 zlib 压缩,在 server 端数据还原,整体裁剪效果:180M—>50M---->13M
=======================================================================
除了通过后台根据 GCROOT+ 引用链自动分配研发跟进解决我们常见的内存泄漏外,我们还对系统导致一些内存泄漏进行了分析和修复。
系统异步 UI 泄漏
根据上传聚合的引用链我们发现在 Android 6.0 以下有一个 HandlerThread 作为 GCROOT 持有大量 Activity 导致内存泄漏,根据引用发现这些泄漏的 Activity 都被一个 Runnable(这里是 Runnable 是一个系统事件 SendViewStateChangedAccessibilityEvent
)持有,这些 Runnable 被添加到一个 RunQueuel 中,这个队列本身被 TheadLocal 持有。