第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 工具选型故障树

根据泄漏特征和开发阶段选择采集工具,下图为决策路径:

数据采集工具选择故障树 应用出现 Handler 泄漏现象 是否已集成 LeakCanary? 已集成:启动 LeakCanary 自动检测 泄漏检测 → 自动导出 .hprof 快照 路径:/sdcard/leakcanary/ 未集成:手动探查 Memory Profiler 实时观察 → Heap dump 导出 .hprof 使用 MAT 分析 .hprof 调引用链 ⚠ 故障树使用说明: LeakCanary 只能检测 Activity/Fragment/View 等常规泄漏;Handler 匿名内部类导致的泄漏同样可检测。 若无法集成 LeakCanary(如系统应用),优先使用 Memory Profiler 定位可疑对象再 dump。

3.2 Memory Profiler:实时监控与触发快照

在 Android Studio 中打开 Profiler 面板,选择 MEMORY 标签。关键操作步骤:

  1. 触发泄漏场景:例如反复进入/退出含 Handler 的 Activity,观察内存曲线是否持续上升而不回落。
  2. 强制 GC:点击 Force garbage collection 按钮(垃圾桶图标),配合 Dump Java heap 按钮生成 .hprof 文件。
  3. 导出快照:在 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 是内存分析核心工具,配置步骤如下:

  1. 从 Eclipse 官网下载 MemoryAnalyzer-1.14.0(最新版),解压后运行 MemoryAnalyzer.exe。
  2. 打开转换后的 .hprof 文件,选择 Leak Suspects Report 模式。
  3. 查看疑似泄漏对象列表,点击 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 导致的具体泄漏引用链,完成原因定位。