第4章 LeakCanary 集成与配置:依赖引入、版本选择、白名单设置、日志输出解读

4.1 现象识别——LeakCanary 不工作或误报

当 LeakCanary 未正确集成时,开发者通常遇到以下三类现象:

  • 静默失效:发生内存泄漏后,通知栏无泄漏图标、Logcat 无 LeakCanary 输出、Heap dump 未生成。
  • 启动崩溃:Application 初始化阶段抛出 ClassNotFoundException 或 NoClassDefFoundError。
  • 误报 / 白名单遗漏:每次 Activity 销毁都报告泄漏,但实际是系统缓存或框架对象,导致无效告警淹没有效泄漏。
现象 直接原因 排查优先级
静默失效 依赖版本不兼容 / 未正确初始化 / ProGuard 混淆规则缺失 高
启动崩溃 依赖坐标错误 / 编译 compileOnly 误用 / 构建变体不匹配 高
误报 白名单未配置 / 白名单类名与实际 GC root 不匹配 中
⚠️ 关键规则: 不要在生产包中启用 LeakCanary 自动 dump。务必使用 debugImplementation 或构建变体限定。参考官方 leakcanary-android-release 的 no-op 模块。

4.2 数据采集——获取配置信息与日志

  1. 确认依赖生效:查看 .gradle 缓存或依赖树
    ./gradlew :app:dependencies --configuration debugImplementation
  2. 抓取 LeakCanary 自身日志:过滤 Logcat tag LeakCanary、LeakCanary-Info、LeakCanary-Debug。典型有效日志:
    D/LeakCanary: LeakCanary is running, ready to detect leaks.
    D/LeakCanary: Watching activity com.example.MainActivity (fragment accepted)
    D/LeakCanary: Scheduling check for retained instances in 5 seconds
    D/LeakCanary: Analysis in progress, working on retained instances...
    D/LeakCanary: Heap dump file path: /data/data/com.example/cache/leakcanary/xxx.hprof
  3. 获取 Heap dump 文件:通过 Device File Explorer 提取 /data/data/{package}/cache/leakcanary/ 目录下的 .hprof。
  4. 白名单配置检查:在 Logcat 过滤 IgnoredClassReachability 可看到哪些类被跳过。例如:
    LeakCanary: IgnoredClassReachability: android.arch.lifecycle.ReportFragment injected by framework - ignoring.
📋 采集清单: 依赖版本号 & 构建变体 → Logcat 全量 LeakCanary 日志 → dump 文件列表 → 白名单生效日志。

4.3 原因定位——故障树分析法

LeakCanary 集成故障树 LeakCanary 不工作 / 误报 静默失效 启动崩溃 误报 依赖未生效 混淆过滤泄漏点 坐标错误 compileOnly 误用 白名单遗漏 类名不匹配 implementation 误写 构建变体限定错 版本号不存在 release 未用 no-op framework 类未忽略 白名单 JSON 语法错误 排查起点: 1. 查看 Logcat 是否打印 "LeakCanary is running" 2. 检查 build.gradle 中依赖的 配置名称 与 构建变体 快速判断规则: • 无日志 → 依赖或初始化错误 • 有日志但无 dump → 白名单或分析器异常

4.4 修复动作——依赖引入、版本选择、白名单配置

4.4.1 依赖坐标与版本选择规则

LeakCanary 版本 Gradle 坐标(debugImplementation) 适用 Gradle / AGP 关键变化
2.7 及之后 com.squareup.leakcanary:leakcanary-android:2.13 AGP 7.0+ / Gradle 7.0+ 支持自动配置;无需手动 install
2.4 – 2.6 com.squareup.leakcanary:leakcanary-android:2.6 AGP 4.2+ / Gradle 6.8+ 需在 Application 中调用 LeakCanary.install(application)
1.6.x com.squareup.leakcanary:leakcanary-android:1.6.3 AGP 3.x 已停止维护;不推荐新项目使用
✅ 版本选择黄金规则:
  • 新项目直接使用 2.13(2024年最新稳定版)。
  • 若项目使用 Java 8 且 AGP ≥ 7.0,首选 2.7+ 系列。
  • 避免使用 SNAPSHOT 或 alpha 版本用于生产调试。

4.4.2 build.gradle 正确配置示例

// app/build.gradle
android {
    // ...
    buildTypes {
        release {
            // 确保 release 构建下没有 LeakCanary 的自动 dump
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    // 仅在 debug 变体引入
    debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.13'
    // release 变体使用 no-op 空模块
    releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:2.13'
    // 可选:测试变体也启用
    testImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:2.13'
}

4.4.3 白名单设置方法

白名单用于跳过已知不构成泄漏的系统对象或框架缓存。在 assets/leakcanary-ignored-classes.txt 中配置,一行一个类全限定名:

# Android framework 常见误报
android.arch.lifecycle.ReportFragment
android.app.ActivityManager
com.android.internal.policy.DecorView
android.view.inputmethod.InputMethodManager

# 第三方 SDK 缓存
com.example.sdk.CommonCache
com.bumptech.glide.manager.SupportRequestManagerFragment

# 自定义接口回调(确认生命周期正确时)
com.example.app.GlobalCallback
⚠️ 白名单陷阱排查规则:
  1. 类名必须与 Heap dump 中的 GC Root 类型完全一致(包含包名)。
  2. 忽略行首空格,但类名后不能有尾随空格。
  3. 可以使用 # 注释,但注释不能写在同一行类名后。
  4. 若白名单不生效,检查文件路径是否准确:应为 src/main/assets/leakcanary-ignored-classes.txt,而非 assets 子目录。

4.4.4 ProGuard / R8 保留规则

若使用混淆,必须保留 LeakCanary 内部类和泄漏分析器:

-keep class leakcanary.** { *; }
-keep class shark.** { *; }
# 如果你手动 install,保留 Application 子类中的 install 调用
-keepclasseswithmembers class * extends android.app.Application {
    public void onCreate();
}

4.5 复测——验证集成生效

  1. 验证依赖生效:在 Application 启动时加一行日志 Log.d("LeakCheck", "LeakCanary installed: " + LeakCanary.isInAnalyzerProcess);(仅在 debug 下)。
  2. 制造人工泄漏:在 Activity 中持有静态 Context 引用,然后快速旋转屏幕,观察 5 秒后是否出现通知。
  3. 检查白名单日志:过滤 IgnoredClass,确认系统类被正确跳过。
  4. 验证 release 包无影响:切换 build variant 到 release,确认 apk 中不包含 leakcanary 相关类(可通过反编译或检查 dex 字节数)。

4.6 预防——集成规范 checklist

检查项 要求 验收方式
依赖限定 debugImplementation 与 releaseImplementation no-op 配对 依赖树输出
版本锁定 使用全平台统一版本号,不应存在多个 LeakCanary 版本 gradle dependencies | grep leakcanary
白名单文件 文件位于 src/main/assets/leakcanary-ignored-classes.txt 手动检查路径
ProGuard 保留 包含 leakcanary 和 shark 包 反编译 release apk
初始化检查 LeakCanary 2.7+ 自动注册,无需手动调用 Logcat 确认
误报监控 每周 review 泄漏报告,确认白名单是否需要更新 持续集成任务
🔧 最佳实践: 在 CI 的 debug 构建中启用 LeakCanary,并编写单元测试验证指定 Activity 在销毁后无 retain 实例。参考 com.squareup.leakcanary:leakcanary-android-instrumentation 模块。