一、架构设计差异
指令集架构
- JVM:基于栈结构,所有操作(如算术运算、方法调用)均依赖操作数栈完成,指令集紧凑但执行效率较低(需频繁内存交互)。
- Dalvik:基于寄存器架构,直接操作虚拟寄存器,指令更少且执行速度更快(如
add-int/2addr
一条指令即可完成加法)。 - ART:继承Dalvik的寄存器架构,但通过AOT预编译直接将字节码转为机器码,避免运行时解释或JIT编译。
字节码格式
- JVM:执行
.class
文件,每个类独立编译,存在冗余信息(如重复字符串常量)。 - Dalvik/ART:使用
.dex
文件,合并多个.class
文件并去除冗余,体积更小(如Google+ APK代码体积减少75%),且支持跨类共享常量池。
- JVM:执行
二、执行机制对比
特性 | JVM | Dalvik | ART |
---|---|---|---|
编译方式 | JIT(运行时编译) | JIT(运行时编译) | AOT(安装时预编译) + JIT(热代码优化) |
启动速度 | 中等(需加载类库) | 慢(首次需JIT编译) | 快(直接执行机器码) |
内存占用 | 高(栈操作频繁) | 中等(寄存器优化) | 低(预编译减少临时对象) |
存储开销 | 低(.class文件) | 低(.dex压缩优化) | 高(预编译机器码增加10%-20%存储) |
三、内存管理与垃圾回收(GC)
JVM
- GC算法:标记-清除(Mark-Sweep)、分代收集(如G1),停顿时间较长。
- 堆管理:每个对象头部存储GC标记,内存碎片化较严重。
Dalvik
- GC机制:采用Mark-Sweep,频繁触发GC(尤其低内存设备),导致界面卡顿。
- 堆分区:分为Zygote堆(预加载核心类)和Active堆(应用对象),通过写时复制(Copy-on-Write)优化进程创建。
ART
- GC优化:引入并发标记-清除(Concurrent Mark-Sweep),减少停顿时间;支持分代GC,提升回收效率。
- 内存分配:采用RosAlloc、BumpPointer等算法,减少碎片化并提升分配速度。
四、性能与适用场景
计算密集型任务
- JVM:通用性强,但效率低于寄存器架构(如ARM设备上浮点运算性能差)。
- Dalvik:JIT动态优化热代码,但运行时编译开销大(如游戏场景CPU占用率高)。
- ART:AOT预编译+JIT混合模式,复杂计算流畅(如3D渲染帧率提升30%)。
多进程与资源隔离
- JVM:单进程多线程,依赖操作系统线程调度。
- Dalvik/ART:每应用独立进程,通过Linux进程隔离保障安全性(如崩溃不影响其他应用)。
五、设计目标与生态定位
JVM:
- 跨平台核心:实现“一次编译,到处运行”,依赖不同平台的JVM实现(如Windows JDK与Linux JDK)。
- 通用性优先:牺牲部分性能换取广泛的硬件兼容性。
Dalvik/ART:
- 移动端优化:针对ARM架构和低功耗设备设计,强调能效比(如ART的AOT编译降低CPU持续负载)。
- 系统集成:深度整合Android特性(如Zygote进程预加载、Binder IPC),提升启动速度和响应能力。
总结
- Dalvik vs JVM:寄存器架构与栈架构的本质差异导致Dalvik在移动端更高效,但JVM的跨平台能力不可替代。
- ART vs Dalvik:AOT预编译彻底解决JIT的运行时开销,但牺牲存储空间换取性能飞跃。
- 适用场景:
- JVM适合服务器和桌面应用,Dalvik/ART专为Android移动生态优化。
- ART的混合编译模式(AOT+JIT)平衡了安装时间与运行效率,成为Android 5.0+的性能基石。