ART GC:垃圾回收机制与卡顿关联
2026/8/9大约 3 分钟运行时Android 14ARTGC回收
ART GC:垃圾回收机制与卡顿关联
上一章看了执行模式。这一章回答:ART 的 GC 怎么工作,回收器有哪些,GC 与卡顿、 内存问题如何关联?
GC 日志要结合分配与暂停时间
| 常见误解 | 正确理解 |
|---|---|
| GC 只在内存满时发生 | 分配压力与阈值都会触发,低内存时更频繁 |
| GC 日志没用 | GC 日志是“为什么卡”的关键证据之一 |
| 所有回收器一样 | 现代 ART 以并发复制(CC)为主,有分代扩展 |
核心结论
- GC 从 root 出发标记可达对象,回收不可达对象。
- 现代 ART 默认并发复制(CC)回收器,追求低停顿。
- 分配压力、内存阈值与低内存信号都会触发 GC。
- GC 日志(如 “Background young CC” 等)可直接看出回收频率与耗时。
- 频繁 GC → 掉帧;OOM → 回收后仍无法分配。
GC 主链
逐步解释:
- 分配:应用不断创建对象。
- 压力:堆用量接近阈值。
- 回收:GC 标记并回收。
- 结果:恢复或 OOM。
怎么读 GC 日志
Background young concurrent copying GC freed 1000 objects, 5ms关键信息:回收类型(young/full)、回收对象数、耗时。短时间内反复出现说明分配过快 或泄漏,是排查卡顿与内存问题的入口。
源码证据
阅读目标:确认 GC 入口。
正文指针:art/runtime/gc/Heap.cpp 的回收流程;art/runtime/gc/collector/ 的 回收器实现。
// art/runtime/gc/Heap.cpp(伪代码,行号以 r75 为准)
void Heap::CollectGarbage(...) {
// 触发回收
}这段代码证明: GC 由堆管理统一调度;日志由回收器输出,可直接用于排查。
验证与排障
环境:开发设备或模拟器;以下命令不需要 root。
adb logcat -v threadtime | grep -E "GC_|concurrent copying|Background"
adb shell dumpsys meminfo <包名> | grep -iE "dalvik|heap"
adb shell am dumpheap <包名> /data/local/tmp/heap.hprof先看 GC 日志的频率与耗时,再查堆用量,最后用 hprof 定位泄漏。卡顿与 GC 同步出现 时,先解决“为什么频繁 GC”。
常见误区
- “GC 只在内存满时”:分配压力与阈值都触发。
- “GC 日志看不懂”:字段有限,一看就会。
- “所有回收器一样”:CC 为主,分代扩展。
- “卡顿都是 GC”:GC 只是常见原因之一。
延伸问题
- CC 回收器如何做到低停顿?
- 分代 GC 的年轻代如何工作?
- GC root 包含哪些对象?
- 如何区分分配过快与泄漏?
源码入口
| 文件 | 关键位置 | 作用 |
|---|---|---|
art/runtime/gc/Heap.cpp | 回收调度 | GC 入口 |
art/runtime/gc/collector/ | 回收器 | 算法 |
| GC 日志 | 运行输出 | 排障证据 |
am dumpheap | hprof | 泄漏定位 |
公共路径:art/runtime/gc/。行号以 r75 检索为准。
代码进入执行前的加载与验证,见 类加载与验证。