ART 运行时与 GC
2026/8/24大约 3 分钟
ART 运行时与 GC
ART(Android Runtime)在 Android 5.0 起取代 Dalvik,引入 AOT 编译并优化了垃圾回收。本章梳理 ART 的核心能力与 GC 方案。
一、ART 与 Dalvik 的区别
| 对比项 | Dalvik | ART |
|---|---|---|
| 编译方式 | JIT(Just-In-Time):解释字节码,运行时编译 | AOT(Ahead-Of-Time):安装时预编译字节码为机器语言 |
| 执行效率 | 需解释器逐条解释,效率低 | 移除解释过程,执行更高效、启动更快 |
| 安装验证 | 较宽松 | 更严格的安装时验证 |
| 占用空间 | 较小 | 安装后占用空间更大(预编译产物) |
ART 引入预先编译机制:安装时使用设备自带的 dex2oat 工具编译应用,该工具接受 DEX 文件作为输入,为目标设备生成经过编译的应用可执行文件。
二、ART 的垃圾回收优化
GC 可能有损于应用性能,导致显示不稳定、界面响应缓慢。ART 通过以下方式优化 GC:
- 只有一次(而非两次)GC 暂停。
- 在 GC 保持暂停状态期间并行处理。
- 清理最近分配的短时对象时,总 GC 时间更短。
- 优化垃圾回收工效,能更及时地进行并行垃圾回收,GC_FOR_ALLOC 事件在典型用例中极为罕见。
- 压缩 GC 以减少后台内存使用和碎片。
三、ART GC 方案
ART 有多个不同的 GC 方案,默认方案是 CMS(并发标记清除),主要使用粘性 CMS 和部分 CMS:
| 方案 | 说明 |
|---|---|
| 粘性 CMS | ART 的不移动分代垃圾回收器,仅扫描堆中自上次 GC 后修改的部分,只能回收自上次 GC 后分配的对象 |
| 部分 CMS | 处理部分堆的并发标记清除 |
| 堆压缩 | 应用进入后台或缓存状态时执行,减少碎片和内存使用 |
除了新的垃圾回收器,ART 还引入基于位图的新内存分配程序 RosAlloc(插槽运行分配器):具有分片锁,分配规模较小时可添加线程本地缓冲区,性能优于 DlMalloc。
四、ART GC 与 Dalvik 的对比
| 对比项 | Dalvik | ART |
|---|---|---|
| 暂停次数 | 2 次 | 1 次(第一次根标记改为并发标记,线程标记自己的根后马上恢复) |
| 暂停期间并发处理 | 少 | Reference 处理、系统弱清除、重新标记非线程根、卡片预清理均并发进行 |
| 粘性回收器 | 无 | 粘性 CMS 增加 GC 吞吐量,年轻对象保存在分配堆栈中,不移动 |
| 移动回收器 | 无 | 引入移动 GC(同构空间压缩、半空间压缩),通过堆压缩减少后台内存 |
移动 GC 的两种方案
- 半空间压缩: 将对象在两个紧密排列的碰撞指针空间之间移动,适合小内存设备,可稍微多节省内存;但应用在前台时 CMS 不能从碰撞指针空间收集,需要再转换一次,可能引起较长暂停。
- 同构空间压缩: 将对象从一个 RosAlloc 空间复制到另一个 RosAlloc 空间,通过减少堆碎片减少内存使用,是目前非低内存设备的默认压缩模式;优势是前后台切换时无需堆转换。
五、开发和调试优化
- 支持采样分析器: 相比 Traceview 逐方法调用的开销,采样分析器不会明显减慢速度,分析更准确。
- 更多调试功能: 查看堆栈跟踪中保留的锁、跳转到持有锁的线程;询问指定类的当前活动实例数;过滤特定实例的事件等。
- 优化异常与崩溃报告: 提供 ClassCastException、ClassNotFoundException、NullPointerException 等更详细的异常信息。