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 底层机制仍有重要意义。


原始标题:What Is the Difference Between DVM and JVM?

« 上一篇: Java周报,347