第3章:泄漏证据采集工具配置
3.1 现象识别与工具选型树
当应用出现卡顿、OOM 或退出后未被回收时,需要立即进入证据采集阶段。不同现象对应不同的首选工具,避免盲目堆砌工具浪费排查时间。
决策原则: 内存泄漏排查 ≠ 全工具启动。根据现象严重程度和可复现性选择工具组合。
现象-工具映射表
| 现象特征 | 推荐启动工具 | 采集目标 |
|---|---|---|
| 应用退出后内存占用不降 | dumpsys meminfo + LeakCanary | 进程存活判定 / 泄漏对象快照 |
| 滑动或点击后反复 GC / 卡顿 | Android Profiler(Memory Profiler) | Java Heap 动态生长曲线 |
| OOM 闪退或大对象无法回收 | MAT(内存分析器) | GC Root 链分析 |
| 多页面跳转后内存持续增长 | LeakCanary + Android Profiler | Activity/Fragment 生命周期残留 |
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 数据采集流程(现象→数据采集)
- 场景复现: 进入目标页面 → 操作泄漏动作(如横竖屏切换、弹窗关闭、Fragment 替换) → 返回上一级
- 启动 LeakCanary: 等待 5 秒,若通知栏出现泄漏提示,点击即可查看引用链
- Profiler 快照: 在操作后立即 Dump Java Heap,保存为
heap_dump.hprof - 命令行验证: 执行
dumpsys meminfo记录 Activities 数量,确认是否超过正常阈值 - 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 中) |