1. 概述
本文将深入探讨 Java 虚拟机(JVM) 与 Dalvik 虚拟机(DVM) 之间的核心差异。我们会先分别介绍两者的基本概念,再从架构、编译、性能和执行方式等维度进行对比。
⚠️ 注意:自 Android 5.0(Lollipop)起,DVM 已被 Android Runtime(ART) 取代。本文讨论的 DVM 主要适用于 Android 4.4 及更早版本。
2. 什么是运行时环境(Runtime)?
运行时环境的作用是将高级语言(如 Java)编写的代码,翻译成 CPU 可直接执行的机器码。它本质上是一个“翻译官”,但实现方式有多种:
- ✅ 汇编器(Assemblers):将汇编语言直接转为机器码,速度快
- ✅ 编译器(Compilers):先将源码编译为汇编代码,再通过汇编器生成机器码。编译慢,但运行快,生成的代码与平台强相关
- ✅ 解释器(Interpreters):边解释边执行,启动快但运行效率低,因为翻译发生在运行时
JVM 和 DVM 都属于这类运行时系统,但设计目标和实现机制大相径庭。
3. Java 虚拟机(JVM)
JVM 是 Java 生态的基石,用于运行桌面、服务端和 Web 应用。它的核心设计哲学是 “一次编写,到处运行”(Write Once, Run Anywhere)。
关键特性包括:
- ✅ 支持跨平台,可在 x86、ARM 等多种架构上运行
- ✅ HotSpot 是 Oracle 官方的 JVM 实现,也是最主流的版本
- ✅ 开源社区还有 OpenJ9、GraalVM 等多个成熟实现
- ✅ 自 Java 9 起采用半年发布周期,持续演进(如 Foreign-Memory Access、JEP 343 打包工具等)
但 JVM 的“通用性”也带来了代价——资源占用较高,不适合内存受限的嵌入式设备。
4. Dalvik 虚拟机(DVM)
DVM 是 Google 为 Android 量身定制的虚拟机,专为移动设备优化。虽然 Android 应用多用 Java 语言编写,但 DVM 并不是 JVM,两者不兼容。
DVM 的设计目标非常明确:
- ✅ 在低内存设备上高效运行
- ✅ 启动速度快
- ✅ 支持多实例并发,每个应用运行在独立的 DVM 实例中
⚠️ 自 Android 5.0 起,DVM 被 ART 取代。ART 采用 AOT(Ahead-of-Time)编译,进一步提升了性能和电池续航。DVM 的最后一个版本是 1.6.0,随 Android 4.4(KitKat)发布。
5. JVM 与 DVM 的核心差异
5.1 架构:栈 vs 寄存器
这是两者最根本的区别。
✅ JVM 是基于栈的虚拟机(Stack-based VM)
所有操作数和中间结果都通过操作栈进行压栈和弹栈。方法调用、局部变量也都依赖栈结构。示例伪代码:
// a + b iload_1 // push a iload_2 // push b iadd // pop a, pop b, push result
✅ DVM 是基于寄存器的虚拟机(Register-based VM)
使用虚拟寄存器存储操作数,指令直接操作寄存器,更接近真实 CPU 的工作方式。示例伪代码(Dalvik 字节码):
add-int v0, v1, v2 // v0 = v1 + v2
📌 简单粗暴地说:JVM 像是用“草稿纸”算题(栈),DVM 则像用“计算器内存”(寄存器),后者在移动设备上更高效。
5.2 编译流程
两者编译路径不同,关键在于中间字节码格式。
✅ JVM 编译流程:
Java 源码 → javac → Java 字节码 (.class) → JVM 解释/编译 → 机器码
✅ DVM 编译流程:
Java 源码 → javac → Java 字节码 (.class) → dx/d8 工具 → Dalvik 字节码 (.dex) → DVM 执行
📌 注意:.dex
文件会将多个 .class
文件合并,减少冗余,优化存储——这对 APK 体积至关重要。
两者都使用 JIT(Just-In-Time)编译器,在运行时将热点代码编译为本地机器码以提升性能。
5.3 性能对比
维度 | JVM(栈式) | DVM(寄存器式) |
---|---|---|
❌ 字节码大小 | 小(操作数隐式在栈上) | 大(操作数显式在指令中) |
✅ 执行速度 | 指令多,分发开销大 | 指令少,执行更快 |
⚠️ 适用场景 | 服务器、桌面(资源充足) | 移动端(资源受限) |
📌 踩坑提示:寄存器式 VM 虽然执行快,但生成的 .dex
文件更大。这也是为什么 Android 构建时会有“Multi-Dex”和“ProGuard”等优化手段。
5.4 执行模型
✅ JVM 通常单实例运行
多个 Java 应用可运行在同一 JVM 实例中,共享堆内存和线程资源(如 Tomcat 部署多个 Web 应用)。✅ DVM 为多实例设计
Android 系统为每个应用或服务创建独立的 DVM 实例,拥有独立进程和虚拟机空间,增强隔离性和安全性。
# 查看 Android 进程(每个应用一个 DVM 实例)
ps -A | grep com.example.myapp
# 输出示例:
# u0_a123 1234 123 123456 78900 ffffffff 00000000 S com.example.myapp
📌 这种设计让 Android 能更好地管理应用生命周期和资源回收。
6. 总结
对比项 | JVM | DVM |
---|---|---|
架构 | 栈式 | 寄存器式 |
字节码 | .class |
.dex |
编译工具 | javac | dx/d8 |
执行模型 | 单实例为主 | 多实例 |
使用场景 | 服务器、桌面 | Android(4.4 及之前) |
现状 | 持续演进 | 已被 ART 取代 |
✅ 一句话总结:JVM 追求通用与跨平台,DVM 专为移动端资源优化而生。虽然 DVM 已成历史,但理解其设计思想,对深入掌握 Android 底层机制仍有重要意义。