Skip to content

LeakCanary 原理与源码解读

核心概述

LeakCanary 是 Square 开源的 Android 内存泄漏检测库,通过自动化监控、堆转储分析和引用链解析,帮助开发者快速定位内存泄漏问题。其核心在于对生命周期敏感对象的监控和智能分析。

模块与架构

  • ObjectWatcher:核心监控器,负责跟踪应被回收的对象
  • HeapDumper:堆内存转储模块,生成 hprof 分析文件
  • HeapAnalyzer:堆分析器,解析 hprof 文件找出泄漏引用链
  • DisplayLeakService:泄漏结果展示服务
  • AndroidWatchExecutor:Android 平台任务调度器

检测流程拆解

  1. 对象监控:Activity/Fragment 销毁后,ObjectWatcher 开始监控这些对象
  2. 延迟检测:等待 5 秒后执行 GC,检查对象是否被回收
  3. 堆转储触发:若对象仍存活,触发堆内存转储生成 hprof 文件
  4. 堆分析:Shark 库解析 hprof,找出到 GC Roots 的引用链
  5. 结果展示:通过通知显示泄漏信息,包括引用路径和泄漏大小
kotlin
// 简化后的监控流程
fun watch(watchedObject: Any, description: String) {
    // 创建弱引用和引用队列监控对象
    val weakReference = KeyedWeakReference(watchedObject, key, description, clock)
    watchedObjects[key] = weakReference
    
    // 延迟检查对象是否被回收
    executor.execute {
        // 触发 GC 并移除可回收的引用
        Runtime.getRuntime().gc()
        System.runFinalization()
        
        // 检查对象是否仍被持有
        if (weakReference.isRetained) {
            // 触发堆转储和分析流程
            dumpHeapAndAnalyze(weakReference)
        }
    }
}

关键源码细节

生命周期监控

  • Activity 监控:通过 Application.ActivityLifecycleCallbacks 监听 onDestroy
  • Fragment 监控:通过 FragmentManager.FragmentLifecycleCallbacks 监听 onDestroy
  • ViewModel 监控:通过 ViewModel 的 onCleared 回调进行监控

引用监控机制

kotlin
class ObjectWatcher {
    private val watchedObjects = mutableMapOf<String, KeyedWeakReference>()
    private val queue = ReferenceQueue<Any>()
    
    fun expectDeletion(
        object: Any,
        reason: String
    ) {
        // 创建带键的弱引用,便于追踪
        val reference = KeyedWeakReference(object, key, reason, queue)
        // 定期检查引用队列,移除已回收的对象
        removeReachableObjects()
    }
}

堆分析优化

  • Shark 分析引擎:替代原来的 HAHA 库,解析速度提升 6 倍
  • 引用链修剪:智能过滤无关引用,突出关键泄漏路径
  • 模式识别:识别常见泄漏模式(如静态引用、内部类持有等)

实践与配置建议

基础集成

kotlin
class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        if (LeakCanary.isInAnalyzerProcess(this)) {
            return
        }
        LeakCanary.install(this)
    }
}

自定义监控对象

kotlin
// 监控自定义对象
AppWatcher.objectWatcher.watch(
    watchedObject = myObject,
    description = "MyObject leaked"
)

// 配置监控范围
LeakCanary.config = LeakCanary.config.copy(
    watchFragmentViews = true,
    watchActivities = true,
    watchViewModels = true
)

高级配置

kotlin
val config = LeakCanary.config.copy(
    // 保留的实例数阈值
    retainedVisibleThreshold = 3,
    // 堆转储触发条件
    dumpHeapWhenDebugging = false,
    // 分析结果处理
    onHeapAnalyzedListener = { heapAnalysis ->
        // 自定义分析结果处理
        uploadToServer(heapAnalysis)
    }
)
LeakCanary.config = config

性能优化策略

分析过程优化

  • 后台分析:堆转储和分析在独立进程进行,不影响主应用
  • 增量分析:只分析相关的对象引用链,减少内存占用
  • 缓存机制:分析结果缓存,避免重复分析相同模式

资源控制

  • 堆转储频率限制:防止频繁堆转储导致性能问题
  • 自动清理:定期清理旧的堆转储文件
  • 内存阈值:设置合理的监控阈值,避免误报

调试与问题排查

常见问题解决

  • 误报处理:配置白名单排除合法持有
  • 分析失败:检查 hprof 文件完整性和权限
  • 性能影响:监控分析进程的 CPU 和内存使用

调试工具

kotlin
// 启用详细日志
LeakCanary.config = LeakCanary.config.copy(
    dumpHeap = true,
    alwaysDumpHeapOnDebug = true
)

// 手动触发堆转储
LeakCanary.dumpHeap()

// 获取分析报告
val heapAnalysis = LeakCanary.analyzeHeap()

扩展与定制

自定义分析器

kotlin
class CustomHeapAnalyzer : HeapAnalyzer(
    listener = OnAnalysisProgressListener { step ->
        // 自定义分析进度监听
    }
)

集成监控系统

kotlin
class UploadLeakService : DisplayLeakService() {
    override fun afterDefaultHandling(heapAnalysis: HeapAnalysis) {
        // 将泄漏信息上传到监控系统
        leakReporter.report(heapAnalysis)
    }
}

LeakCanary 通过这种自动化的监控-检测-分析流程,大大降低了 Android 应用内存泄漏的排查成本,是性能优化不可或缺的工具。