第3章 数据采集工具链:Memory Profiler、Heap dump、MAT、LeakCanary配置与快照导出
当应用出现 Handler 耦合泄漏 的预兆(如卡顿、OOM 或显存常量增长)后,排查进入 数据采集 阶段。本章搭建完整工具链:Android Studio Memory Profiler 用于实时监控,Heap dump 用于获取快照,MAT (Memory Analyzer Tool) 用于离线分析,LeakCanary 用于自动检测与快照导出。四者协作覆盖 从现象到根因 的所有数据需求。
▶ 核心原则:先自动(LeakCanary)后手动(Profiler+MAT),先全局(Heap dump)后局部(引用链)。不要在泄漏未确认前做盲目导出,避免数据噪声。
3.1 工具选型故障树
根据泄漏特征和开发阶段选择采集工具,下图为决策路径:
3.2 Memory Profiler:实时监控与触发快照
在 Android Studio 中打开 Profiler 面板,选择 MEMORY 标签。关键操作步骤:
- 触发泄漏场景:例如反复进入/退出含 Handler 的 Activity,观察内存曲线是否持续上升而不回落。
- 强制 GC:点击 Force garbage collection 按钮(垃圾桶图标),配合 Dump Java heap 按钮生成 .hprof 文件。
- 导出快照:在 Heap dump 条目上右键 → Export to standard .hprof,保存为 .hprof 文件。
⚠ 注意:Memory Profiler 导出的 .hprof 是Android 专用格式,MAT 不能直接打开。需要使用 Android Studio 的 sdk/tools/hprof-conv 工具转换为标准格式:
hprof-conv dump.hprof dump_standard.hprof
3.3 Heap dump 手动导出(命令行方式)
当 Profiler 不适用(如远程设备或自动化测试)时,使用 adb 进行 dump:
# 获取目标进程 PID
adb shell ps | grep com.example.app
# 例如 PID 为 12345,执行 dump
adb exec-out run-as com.example.app am dumpheap 12345 /data/local/tmp/dump.hprof
adb pull /data/local/tmp/dump.hprof ./dump.hprof
# 转换格式(如需要)
hprof-conv dump.hprof dump_std.hprof
3.4 MAT 配置与引用链分析
MAT 是内存分析核心工具,配置步骤如下:
- 从 Eclipse 官网下载 MemoryAnalyzer-1.14.0(最新版),解压后运行
MemoryAnalyzer.exe。 - 打开转换后的 .hprof 文件,选择 Leak Suspects Report 模式。
- 查看疑似泄漏对象列表,点击 See stack trace 查看引用链。
针对 Handler 泄漏,重点关注:
- android.os.Message 对象是否持有 Activity/Context 引用。
- android.os.Handler 内部类是否隐式持有外部类对象。
- GC Root -> Handler -> MessageQueue -> Message -> target(Handler) -> 外部类 这条路径。
📊 分析过滤技巧:在 MAT 的 OQL 查询中输入以下语句,快速定位泄漏的 Handler 相关对象:
SELECT * FROM android.os.Handler WHERE this.mCallback != null
SELECT * FROM android.os.Message WHERE this.target.mContext != null
3.5 LeakCanary 配置与快照导出
LeakCanary 2.x 集成简便,支持自动快照保存。在 build.gradle 中添加:
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.12'
无需额外初始化,默认监听所有 Activity 和 Fragment。快照导出路径默认为 /sdcard/leakcanary/,可通过配置修改:
// Application 中自定义
LeakCanary.config = LeakCanary.config.copy(
eventListeners = listOf(MyEventListener()),
heapDumper = MyHeapDumper()
)
查看并导出快照:
# 查看所有已生成的 .hprof
adb shell ls /sdcard/leakcanary/
# 拉取最新文件
adb pull /sdcard/leakcanary/leakcanary_com.example.app_20250315_103448.hprof .
💡 建议:LeakCanary 导出的 .hprof 已经是标准格式,可直接被 MAT 打开,无需转换。同时会生成 .leakcanary 元数据文件,包含泄漏摘要文本。
3.6 工具对比与选用规则
| 工具 | 适用场景 | 输出格式 | 自动化程度 | 缺点 |
|---|---|---|---|---|
| Memory Profiler | 开发阶段实时监控 | .hprof (Android 格式) | 半自动 | 需人工判断、导出后需转换 |
| Heap dump (adb) | 自动化测试、无界面场景 | .hprof (Android 格式) | 脚本化 | 同样需转换、不能实时观察 |
| MAT | 离线深度分析 | 标准 .hprof | 无自动化 | 学习曲线高、内存消耗大 |
| LeakCanary | 用户端/crash 后自动采集 | 标准 .hprof + 摘要 | 全自动 | 需集成依赖、只检测特定类型泄漏 |
3.7 数据采集质量检查清单
每次采集后,确认以下条件:
- ☐ 快照文件时间戳与泄漏触发时刻匹配(误差 < 10s)
- ☐ .hprof 文件大小 > 5 MB(避免空快照)
- ☐ MAT 打开后无“无法解析”错误(确认已转换标准格式)
- ☐ LeakCanary 摘要中包含 Handler 或 Message 关键字
- ☐ 至少保留 2~3 次不同操作序列的快照(用于对比)
⚠ 常见陷阱:Memory Profiler 导出时若进程被强行 kill,快照可能不完整;LeakCanary 在低内存设备上可能丢弃快照。建议同时保留 adb dump 作为后备。
→ 下一步(第4章):将采集到的 .hprof 送入 MAT,利用 支配树 和 GC Root 查询 定位 Handler 导致的具体泄漏引用链,完成原因定位。