第3章:泄漏证据采集工具配置

3.1 现象识别与工具选型树

当应用出现卡顿、OOM 或退出后未被回收时,需要立即进入证据采集阶段。不同现象对应不同的首选工具,避免盲目堆砌工具浪费排查时间。

决策原则: 内存泄漏排查 ≠ 全工具启动。根据现象严重程度和可复现性选择工具组合。

现象-工具映射表

现象特征 推荐启动工具 采集目标
应用退出后内存占用不降 dumpsys meminfo + LeakCanary 进程存活判定 / 泄漏对象快照
滑动或点击后反复 GC / 卡顿 Android Profiler(Memory Profiler) Java Heap 动态生长曲线
OOM 闪退或大对象无法回收 MAT(内存分析器) GC Root 链分析
多页面跳转后内存持续增长 LeakCanary + Android Profiler Activity/Fragment 生命周期残留
泄漏工具选型决策树 确认内存泄漏现象 可复现 & 无立即OOM 严重OOM / 系统杀死 LeakCanary 监控初始化 dumpsys meminfo + MAT Android Profiler 日常监控 导出 .hprof → MAT 分析 统一证据采集 说明: 🔹 LeakCanary 适用于开发 debug 版本,实时侦测 Activity/Fragment/ViewModel 泄漏。 🔹 Android Profiler 与 MAT 互补:Profiler 发现趋势,MAT 精确定位 GC Root。 🔹 dumpsys meminfo 适合线上/无 IDE 环境快速评估泄漏规模。

3.2 工具配置标准步骤

3.2.1 LeakCanary — 自动泄漏侦测

集成 LeakCanary 只需在 build.gradle 添加依赖,并在 Application 中初始化。推荐使用 2.x 版本,零配置自动监听。

// app/build.gradle
dependencies {
    debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.10'
    // release 版本无需引入
}

// Application.onCreate()
if (LeakCanary.isInAnalyzerProcess(this)) {
    // 当前进程是 Heap Analyzer 进程,不要执行其他初始化
    return;
}
LeakCanary.config = LeakCanary.config.copy(
    retainedVisibleThreshold = 5,  // 保留对象超过5个再通知
    maxStoredHeapDumps = 3         // 最多保存3个堆转储
)
验证配置: 打开 Debug 构建的 App,执行一个 Activity 跳转并返回。等待几秒后 Logcat 应出现LeakCanary: LeakSingleton: ... 提示。若无输出,检查 Application 初始化是否正确。

3.2.2 Android Profiler — 实时内存曲线

无需额外代码,通过 Android Studio 启动即可。但需注意:Profiler 会引入一定性能开销,仅用于调试环境。

  • 打开 Android Studio → View → Tool Windows → Profiler
  • 选择设备和进程,点击 Memory 图标
  • 默认显示 Java Heap / Native Heap / Graphics / Stack / Code 图例
  • 关键操作: 在内存增长点点击 Dump Java Heap 生成 .hprof 文件
避坑: 使用 Android Profiler 采集时应保持系统稳定,避免同时运行其他性能工具(如 Systrace),防止采样冲突导致数据中断。

3.2.3 dumpsys meminfo — 命令行快照

适用于自动化测试或远程排查,无需图形界面。常用命令:

# 查看所有进程内存概览
adb shell dumpsys meminfo

# 仅查看目标进程
adb shell dumpsys meminfo com.example.myapp

# 输出到文件便于对比
adb shell dumpsys meminfo com.example.myapp > mem_before.txt

# 模拟页面操作后再次采集
adb shell dumpsys meminfo com.example.myapp > mem_after.txt

# 查看详细对象计数(含 ViewRootImpl、Activity 等)
adb shell dumpsys meminfo --unreachable com.example.myapp

采集原则: 每次操作前后均执行一次,记录 Total PSS 与 Objects 数(尤其是 Activities 和 ViewRootImpl 数量)。若 Activities 数量持续增长不退,必存在泄漏。

3.2.4 MAT (Memory Analyzer Tool) — 堆转储分析

MAT 用于分析 .hprof 文件。Android 导出的 .hprof 需转换为标准格式才能被 MAT 识别:

# 转换 Android .hprof → 标准 Java .hprof
hprof-conv dump_heap.hprof dump_std.hprof

# 在 MAT 中打开 dump_std.hprof
# 使用 "Leak Suspects Report" 自动扫描
# 或 "Dominator Tree" 查看最大对象保留树
MAT视图 用途 泄漏排查典型操作
Leak Suspects Report 自动列出疑似泄漏点 优先检查 Activity / Fragment / ViewModel 实例
Dominator Tree 显示对象保留规则 找到 Context 对象,查看 GC Root 到它的最短路径
Thread Overview 检查线程栈是否存在 Activity 引用 搜索 android.app.Activity 或 android.view.View

3.3 数据采集流程(现象→数据采集)

  1. 场景复现: 进入目标页面 → 操作泄漏动作(如横竖屏切换、弹窗关闭、Fragment 替换) → 返回上一级
  2. 启动 LeakCanary: 等待 5 秒,若通知栏出现泄漏提示,点击即可查看引用链
  3. Profiler 快照: 在操作后立即 Dump Java Heap,保存为 heap_dump.hprof
  4. 命令行验证: 执行 dumpsys meminfo 记录 Activities 数量,确认是否超过正常阈值
  5. MAT 深入分析: 转换 .hprof,使用 “Leak Suspects” 查看建议的 GC Root
判断规则: 若 Dump 中同一 Activity 实例出现 2 个及以上(且非多实例场景),即可判定为泄漏。若 ViewModel 持有 Context 且未清理,其整个保留树将显示一个长 GC Root 链,通常指向 Thread、Static 变量或 Application 生命周期。

3.4 常见配置陷阱

工具 典型问题 解决
LeakCanary Release 包也打包了进去 使用 debugImplementation 而非 implementation
Android Profiler Dump 失败或空文件 检查进程是否被调试器断开,重新连接
dumpsys meminfo Total PSS 数据波动大 采集前手动触发 GC:adb shell am force-gc com.example.myapp
MAT 打不开转换后的 .hprof 确保使用 hprof-conv 工具(在 Android SDK platform-tools 中)

3.5 小结:工具组合预案