第1章 泄漏现象识别
LiveData Observer 未移除是 Android 开发中最容易忽视的内存泄漏场景之一。Observer 持有 Activity 或 Fragment 的匿名内部类引用,若在页面销毁后未主动移除,将导致页面实例无法被 GC 回收,进而引发一连串可观测的负面现象。
本章聚焦于 现象识别 阶段,帮助开发者快速通过运行时指标和工具判断是否发生了 Observer 泄漏。
1.1 泄漏现象一览
| 可观测现象 | 典型表现 | 判断依据 |
|---|---|---|
| 内存持续增长 | 反复进入/退出页面后,总内存(Native+Java)曲线稳步上升,从不回落至基线 | 使用 Memory Profiler 观察多次操作后的堆内存折线图 |
| GC 频繁 | Logcat 中出现连续 ConcurrentGC 或 AllocGC,间隔小于 1 秒 |
日志搜索 GC freed,统计每分钟 GC 次数 |
| OOM 风险 | 高版本 Android 抛出 OutOfMemoryError;低版本出现 ExceptionInInitializerError |
Crash 报告或 Logcat 中 OutOfMemoryError 堆栈 |
| Activity 实例未释放 | 退出页面后,Activity#onDestroy 已调用,但 Activity 对象仍存在于堆中 |
Dump HPROF 后搜索 Activity 全类名,检查实例数 |
经验规则:若退出页面后托管了
LiveData 的 Activity 实例数 > 1,且 Observer 被生命周期为 “ALWAYS” 的 LifecycleOwner 注册,即可高度怀疑 Observer 未移除泄漏。
1.2 故障树:从现象到可疑原因
以下故障树帮助你在定位时快速缩小范围:
现象:内存曲线持续上升且不下降
├─ 是 → GC 日志是否频繁(> 10次/分钟)?
│ ├─ 是 → 堆转储中 Activity 实例数 > 1?
│ │ ├─ 是 → Observer 未移除(本章重点)
│ │ └─ 否 → 检查其他静态引用泄漏(全局单例、列表等)
│ └─ 否 → 检查图片/视频资源泄漏或 Native 内存泄漏
└─ 否 → 观察是否有 OOM 崩溃?
├─ 是 → 确认崩溃堆栈是否包含 LiveData 相关类
└─ 否 → 正常应用内存波动
1.3 排查表:三步快速判定
- 第一步:打开 Memory Profiler,多次进入/退出目标页面,观察 “Java Heap” 折线 —— 若每次退出后堆内存没有回到操作前的基准值,说明有对象驻留。
- 第二步:抓取 HPROF dump,搜索 Activity 类名,检查实例数量。正常应为 0(已销毁);若存在 1 个或更多,则 Activity 实例被意外持有。
- 第三步:查看保留引用链,在 HPROF 中展开 GC Root 路径,若看到
LiveData.mObservers或ObserverWrapper,即可确认 Observer 未移除。
1.4 现象识别流程图
1.5 典型日志示例
使用 adb logcat -s GC 可实时查看 GC 行为。以下是一条频繁 GC 的日志示例:
I/art: Background GC all threads suspended took 13.294ms
I/art: Background GC all threads suspended took 11.122ms
I/art: Background GC all threads suspended took 14.005ms
I/art: Alloc concurrent mark sweep GC freed 2(128KB) AllocSpace objects, 0(0B) LOS objects, 12% free, 14MB/16MB, paused 1.805ms total 17.094ms
若在退出页面后,该日志持续输出且 14MB/16MB 比例的 分配后堆大小 不回落,说明存在长期存活的对象。
⚠ 常见误区:只靠 “内存增长” 判断泄漏可能误报。必须结合 Activity 实例数 和 引用链 双重确认。LiveData Observer 泄漏的特殊性在于:Observer 持有 LifecycleOwner 的强引用,而 LiveData 通过
mObservers 持有 Observer,形成 LiveData → Observer → Activity 的泄漏链。
1.6 小结
本章明确了 Observer 未移除泄漏的四种核心现象:内存持续增长、GC 频繁、OOM 风险以及 Activity 实例未释放。通过故障树、排查表和流程图,你可以快速从应用卡顿逐步追溯到 LiveData 的 Observer 残留。下一阶段(第2章起)将深入数据采集和引用链分析,但前提是你能准确识别出上述现象。