LeakCanary 原理与源码解读
核心概述
LeakCanary 是 Square 开源的 Android 内存泄漏检测库,通过自动化监控、堆转储分析和引用链解析,帮助开发者快速定位内存泄漏问题。其核心在于对生命周期敏感对象的监控和智能分析。
模块与架构
- ObjectWatcher:核心监控器,负责跟踪应被回收的对象
- HeapDumper:堆内存转储模块,生成 hprof 分析文件
- HeapAnalyzer:堆分析器,解析 hprof 文件找出泄漏引用链
- DisplayLeakService:泄漏结果展示服务
- AndroidWatchExecutor:Android 平台任务调度器
检测流程拆解
- 对象监控:Activity/Fragment 销毁后,ObjectWatcher 开始监控这些对象
- 延迟检测:等待 5 秒后执行 GC,检查对象是否被回收
- 堆转储触发:若对象仍存活,触发堆内存转储生成 hprof 文件
- 堆分析:Shark 库解析 hprof,找出到 GC Roots 的引用链
- 结果展示:通过通知显示泄漏信息,包括引用路径和泄漏大小
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 应用内存泄漏的排查成本,是性能优化不可或缺的工具。