对比Android的两大运行时环境:Dalvik 和 ART。这次对比不仅会讲技术细节,还会从演进的角度分析它们的设计哲学和实际影响。
一、核心概念与设计哲学
Dalvik:为早期Android设计的虚拟机
- 诞生时间:Android诞生之初到Android 4.4
- 设计目标:在资源受限的早期设备(低内存、低CPU性能)上高效运行
- 核心理念 :JIT编译 + 基于寄存器的架构
ART:面向未来的现代化运行时
- 诞生时间:Android 4.4(实验性)→ Android 5.0(正式默认)
- 设计目标:提升性能、流畅度和能效,适应更强大的硬件
- 核心理念 :AOT编译 + 性能优化优先
二、详细技术对比
| 对比维度 | Dalvik | ART |
|---|---|---|
| 编译方式 | JIT | AOT + JIT(Android 7.0后混合模式) |
| 安装时间 | 快 | 较慢 (早期纯AOT版本)→ 优化后接近(混合模式) |
| 应用启动速度 | 较慢 | 显著更快 |
| 运行时性能 | 需要实时编译,有性能开销 | 预编译为本地代码,执行效率高 |
| 内存占用 | 运行时内存占用相对较低 | 安装后占用更多存储空间(存储odex文件) |
| 电池消耗 | 运行时编译消耗额外电量 | 运行时电量消耗更低 |
| 垃圾回收 | 简单的Stop-the-World GC | 更先进的并发GC,减少卡顿 |
| 架构设计 | 基于寄存器 | 基于寄存器(保持兼容) |
| 调试支持 | 相对简单 | 提供更丰富的性能分析工具 |
三、深度技术解析
1. 编译模型的根本差异
Dalvik的JIT工作流程:
.dex文件 → 解释执行 → 热点代码识别 → JIT编译为本地代码 → 缓存并执行
- 优点:安装快,不占用额外存储
- 缺点:每次启动都需要重新编译热点代码,造成启动慢和运行时卡顿
ART的演进:
a) 初期纯AOT(Android 5.0-6.0):
.dex文件 → 安装时完全编译为本地代码 → 直接执行本地代码
- 优点:运行时性能极佳
- 缺点:安装时间很长,占用存储空间大
b) 现代混合模式(Android 7.0+):
.dex文件 → 安装时快速编译(不优化)→ 解释执行 →
JIT分析热点代码 → 后台AOT优化热点代码
这是目前最智能的模式,平衡了安装速度、运行性能和存储占用。
2. 垃圾回收机制的对比
Dalvik GC的问题:
- 完全Stop-the-World:GC发生时,所有应用线程暂停
- 频繁GC:内存管理效率低,导致明显的卡顿
- 两次暂停:一次标记,一次清理,用户体验差
java
// 在Dalvik时代,开发者需要非常小心地避免内存抖动
// 因为频繁GC会导致明显的卡顿
for (int i = 0; i < 10000; i++) {
String temp = new String("item" + i); // 在循环内创建大量对象→频繁GC
// ...
}
ART GC的改进:
- 并发标记:大部分标记工作与应用线程并发执行
- 并发清理:减少暂停时间
- Generational Collection:分代回收,更高效
- 更少的暂停:大幅减少卡顿现象
3. 64位支持
- Dalvik:主要支持32位
- ART:从开始就为64位设计,更好地利用现代CPU架构
四、实际开发影响
对开发者的直接影响
1. 应用性能表现
kotlin
// 在ART环境下,以下代码会有更好的性能表现
class MainActivity : AppCompatActivity() {
// 冷启动速度明显提升
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 方法调用在ART中执行更快(已预编译)
initializeViews()
loadData()
}
private fun initializeViews() {
// ART的AOT编译使这些方法调用更高效
recyclerView.layoutManager = LinearLayoutManager(this)
adapter = MyAdapter(createLargeList()) // 大列表操作更流畅
}
private fun createLargeList(): List<String> {
// 在ART中,对象创建和垃圾回收更高效
return List(1000) { "Item $it" }
}
}
2. 安装体验变化
- Dalvik时代:应用安装飞快,但首次启动慢
- ART早期:安装等待时间长,但启动快
- ART现代:安装速度优化,兼顾启动性能
3. 调试和优化
bash
# ART提供了更好的性能分析工具
adb shell cmd package compile -f -m speed com.example.myapp
# 强制以速度模式编译应用
# 查看编译状态
adb shell dumpsys package dexopt
五、演进历程与现状
历史时间线
- Android 1.0-4.4:Dalvik统治时期
- Android 4.4:ART作为实验性功能引入
- Android 5.0:ART正式取代Dalvik(纯AOT模式)
- Android 7.0:引入JIT+ AOT混合模式,解决纯AOT的问题
- Android 8.0+:持续优化Profile-guided compilation
- Android 10+:对云编译的支持,进一步提升性能
当前现状
- Dalvik:已完全被ART取代,仅存在于历史版本中
- ART:成为现代Android的基石,持续演进优化
- 对开发者:大多数情况下无需关心底层差异,ART自动优化
六、总结:为什么ART是必然选择
| 方面 | Dalvik的局限 | ART的解决方案 |
|---|---|---|
| 用户体验 | 启动慢、运行卡顿 | 启动快、运行流畅 |
| 硬件发展 | 适合早期弱硬件 | 充分利用现代强大硬件 |
| 能效比 | 运行时编译耗电 | 预编译节省电量 |
| 内存管理 | 低效GC导致卡顿 | 并发GC减少暂停 |
| 未来准备 | 32位架构限制 | 原生64位支持 |
技术演进启示 : ART取代Dalvik体现了移动计算发展的必然趋势------用存储空间和安装时间换取运行时性能和能效提升。这种权衡在现代硬件条件下是完全合理的,因为存储空间越来越廉价,而用户体验和电池续航始终是核心诉求。
对于Android开发者来说,理解这个演进过程有助于我们:
- 更好地分析应用性能问题
- 优化应用启动时间和内存使用
- 适配不同Android版本的特性
- 理解Android系统底层的工作原理
ART的胜利标志着Android从"能用"到"好用"的重要转折点。