判断 LeakCanary 报告的严重程度,可以从几个维度来系统分析,而不是简单看 "Leaking: YES"。
一、核心思路
LeakCanary 报告其实告诉你三个信息:
- 泄漏对象:哪个对象被 GC Root 持有?
- 引用链长度:多少中间对象持有泄漏对象?
- 泄漏对象大小 & 类型:Activity、Adapter、Bitmap、数组等
严重程度 = 泄漏对象价值 + 保留时间 + 内存消耗 + 频率
二、判断维度
1️⃣ 对象类型
- Activity / Fragment / View
- 高危对象
- 占用内存大、生命周期短 → 如果泄漏会累积,必须修
- Bitmap / Drawable / 大数组
- 占用显著内存 → 会导致 OOM
- 普通数据对象 / String / 小对象
- 小体量,偶尔泄漏 → 可以低优先级
例如:
- 泄漏对象 =
ListingPhotosActivity - 类型 = Activity
- 占用内存 = 66.5 KB(但整个 Adapter 占 375 KB + Bitmap)
- ✅ 高优先级修复
2️⃣ 生命周期
例如LeakCanary 会告诉你 mDestroyed = true
- 说明对象已经完成生命周期,本应被回收
- 如果 leak 对象生命周期短,但被保留 → 高危
3️⃣ 保留时间(watchDurationMillis & retainedDurationMillis)
watchDurationMillis= 被监控时间retainedDurationMillis= 被保留时间- 时间越长 → 泄漏可能越严重
例如:
watchDurationMillis = 21240
retainedDurationMillis = 16238
- 约 16秒被保留
- 对 Activity 来说,属于典型泄漏(很可能在快速翻页时积累)
4️⃣ 内存消耗量
例如
- LeakCanary 会给你 Retaining size
- Activity 66.5 KB + Adapter 375 KB
- 多次泄漏叠加 → 可导致内存压力或 OOM
5️⃣ 泄漏频率
- 在 UI 中重复操作触发
- 例如:
- 多次打开照片列表页 → 每次 leak
- 高频 + 高内存 → 必须修
6️⃣ 影响用户体验
- 泄漏可能导致:
- 滑动卡顿(内存压力大)
- 图片加载失败
- OOM crash
三、快速评估严重程度方法
| 维度 | 高危 | 中危 | 低危 |
|---|---|---|---|
| 对象类型 | Activity / Fragment / 大View | Adapter / Bitmap | 小对象、String |
| 内存大小 | >100KB / Bitmap >1MB | 50~100KB | <50KB |
| 生命周期 | 短生命周期被保留 | 长生命周期被保留 | 常驻对象 |
| 被触发频率 | 高 | 中 | 低 |
| 用户影响 | crash / 卡顿 | 内存增加 | negligible |
例如:
- Activity + Adapter + 图片 → 高危
- 建议 必须修复,尤其是高频页面(Slideshow / Carousel)
四、实战 QA 建议
1️⃣ 快速复现泄漏
- 复现泄漏场景
- 重复 10-20 次
- 看 LeakCanary 堆积对象数量
2️⃣ 对比修复前后
- LeakCanary 会显示:
- Retaining size 减少
- ObjectWatcher 不再报警
3️⃣ 对移动端性能影响评估
- 结合 Android Profiler
- 观察:
- 内存使用曲线
- GC 频率
- 如果泄漏累积 → 高概率 OOM
五、总结判断逻辑
判断 LeakCanary 泄漏严重程度时,通常会看:
- 泄漏对象类型和内存大小(Activity、Bitmap 优先修复)
- 生命周期是否短却被保留(mDestroyed = true)
- 被保留的时间和频率(频繁触发 + 保留时间长 → 高危)
- 是否影响用户体验(滑动卡顿、OOM)