Systemui Java堆-Hprof对比分析
Showmap统计java堆,gc之后,P1 44M/magic 25M,相差约19M
[附件: ZNDabXMnworWBCx28FdctEp7nKc]

Hprof统计到的堆内存,P1 57.6M/magic 49.3M,相差约8.3M
虽然数据无法对上,但是java堆总体趋势P1确实差于magic,目前建议通过hprof分析
[附件: JrBcb94zzo2oftxjMKbcLQK9nih]
[附件: K5JabeTBfoa0PUxeLqrcGnGMnoe]
👀 为什么 HPROF(57.6M)> showmap(44M)? showmap中统计规则有问题,后续会和meminfo中的java heap大致保持一致 最终使用hprof分析,业务侧可以以hprof展示的堆内存占用为准
对比分析P1和magic的Hprof,并附上详细步骤
预置条件:
使用自动化工具(推荐):
- 安装JDK,配置环境变量:MAT要依赖java环境
- 安装HprofMatOpener-Installer-Bundled:
[附件: X7PybO0KbolRshxLEZuc8ncAn2b]
- 具体使用可查看:
[附件: ScTSbauZOoyWTOx7Q49cCabZnWn]
- 安装完成之后,双击任何从手机中pull出的hprof即可在mat中打开,无需环境依赖和格式转换
PS:之前的hprof_manager.exe存在一些信息丢失的问题,会造成hprof文件较小,请使用上述最新版本
或者手动一步步安装环境依赖:
- 安装MAT:
[附件: CZ2xbuG1Foz4PMx0uZscrNgMnec]
- 安装JDK
- adb抓取hprof:
adb shell am dumpheap 包名/PID(建议使用pid) /data/local/tmp/test.hprof- 格式转换:
[附件: CrX2bHe5eoBlvXxiSvCcyByPn6f]
hprof-conv.exe 是 Android SDK 自带的工具,作用是将 Android 设备上生成的原始 hprof 文件转换为标准 JVM 格式
hprof-conv.exe test.hprof test.hprof对比分析步骤:
1.同时打开两个hprof文件:

2.打开Histogram(堆直方图)
在 MAT 中,Histogram(堆直方图) 是最基础且常用的内存分析工具之一,它会按照类名对堆中所有对象进行分组统计,直观展示每个类的对象数量、内存占用情况
定位大对象 / 高频对象:找出占用内存最多、对象数量最多的类,缩小问题范围。

补充说明
[嵌入表格]
和 Dominator Tree(支配树)的区别:Histogram 是 “类” 维度的统计,而 Dominator Tree 是 “单个对象” 维度的统计。
- 如果你想知道 “哪个类的对象整体占用内存最多”,用 Histogram;
- 如果你想知道 “哪个具体对象占用内存最多”,用 Dominator Tree
3.结合 Compare Tables 功能,对比两个快照的 Histogram,发现类的对象 / 内存变化,定位差别对象
分别将两个hprof的Histogram添加到Compare Basket


点击”红色叹号”,生成Compared Tables

为了方便对比,可以导出到csv进行diff排序,选取top差异的类对象进行分析:

4.Mat继续定位类对象引用链,进而定位业务侧具体逻辑
以com.android.systemui.statusbar.StatusBarIconView此类对象为例

P1 上存在大量额外的 StatusBarIconView 对象,比对比机多170个StatusBarIconView对象
进一步分析:
Merge Shortest Paths to GC Roots:把所有 StatusBarIconView 实例到 GC 根引用的最短路径合并,找出它们的共同根引用,快速定位这一类对象的统一持有者。
exclude all phantom/weak/soft etc. references:排除虚引用、弱引用、软引用等引用类型,只保留强引用,这样能精准定位那些真正导致对象无法被回收的根引用。

测试机 244 个 StatusBarIconView 实例,最终被 9 个不同的根引用持有
对比机 74 个StatusBarIconView 实例,最终被 2 个不同的根引用持有


进一步展开上述第一个结果:展示了 StatusBarIconView 到根引用(ContentObserver$Transport)的最短路径,以及路径上的关键节点(如 CollapsedStatusBarFragment、MuiStatusIconContainer)

对于这种批量分析差异的情况,比较适合最短路径的根引用,进一步展开:即可看到37个StatusBarIconView 详细信息和地址

5.竞品机magic同样的操作展开相关引用链,即可定位到差异根源
👀 最终结论: 与业务讨论,多状态栏/怀疑对比机相关图标进行了懒加载(lazy mode),导致状态栏/下拉通知栏的图标数量/堆内存差异,后续业务模块会进一步给出修改方案
另外一个分析案例可以查看:Systemui hprof分析实操