3.1 Dalvik VM和JVM的差异

很多人认为Dalvik VM是一个Java虚拟机,因为Android的编程语言恰是Java语言。但是这种说法并不准确,因为Dalvik虚拟机并不是按照Java虚拟机的规范来实现的,两者并不兼容。其中有如下两个显著的不同点。

Java虚拟机运行的是Java字节码,而Dalvik虚拟机运行的则是其专有的文件格式dex(Dalvik Executable)。

在Java SE程序中的Java类会被编译成一个或者多个字节码文件(.class)然后打包到JAR文件,而后Java虚拟机会从相应的CLASS文件和JAR文件中获取相应的字节码;Android应用虽然也是使用Java语言进行编程,但是在编译成CLASS文件后,还会通过一个工具(dx)将应用所有的CLASS文件转换成一个DEX文件,而后Dalvik虚拟机会从其中读取指令和数据。

Dalvik VM与大多数虚拟机和真正的Java VM不同,它们是栈机(Stack Machine),而Dalvik VM是基于寄存器的架构。此外,两种方法的相对优势取决于所选择的解释/编译策略。但总的来说,基于stack的机器必须使用指令来载入stack上的数据,或使用指令来操纵数据。所以与基于寄存器的机器相比,Dalvik VM需要更多的指令。然而,在寄存器的指令必须编码源和目的地寄存器,因此往往指令更大。

在Dalvik VM机制中,使用一个名为dx的工具来转换Java的.class文件到.dex格式。多个类文件可包含到单个的.dex文件中,重复的、可用于多个类的字符串和其他常量在转换到.dex格式时输出到保留空间。Java字节码还可转换成可选择的、Delvik VM使用的指令集。一个未经过压缩的.dex文件,在文件大小方面往往比从同样的.class文件压缩成的.jar文件更小。

当Dalvik可执行文件安装到移动设备时,它们是可以被修改的。为了进一步优化,在某些数据、简单数据结构和内联的函数库中的字节顺序可以互换,例如空类对象被短路。

为了满足低内存要求而不断优化,Dalvik VM存在如下所示的独特特征。

(1)Dalvik VM很小,使用的空间也小。

(2)Dalvik VM没有JIT编译器。

(3)Dalvik VM常量池已被修改为只使用32位的索引,以简化解释器。

(4)Dalvik VM使用自己的字节码,而非Java字节码。

此外,Dalvik VM被设计来满足可高效运行多种虚拟机实例。Dalvik VM和标准Java虚拟机(JVM)之间的首要差别之一,就是Dalvik VM基于寄存器,而JVM基于栈。Dalvik VM和JVM之间的另外一大区别就是运行环境——Dalvik VM经过优化,允许在有限的内存中同时运行多个虚拟机的实例,并且每一个Dalvik VM应用作为一个独立的Linux进程执行。

具体来说,Dalvik虚拟机和Java虚拟机的差异如下所示。

Dalvik虚拟机早期并没有使用JIT(Just-In-Time)技术,从Android 2.2版本开始,Dalvik虚拟机也支持JIT。

Dalvik虚拟机有自己的bytecode,并非使用Java bytecode。

Dalvik虚拟机基于暂存器(register),而JVM基于堆栈(stack)。

Dalvik VM通过Zygote进行Class Preloading, Zygote会完成虚拟机的初始化,也是与JVM的不同之处。

概括来说,Dalvik虚拟机和Java虚拟机的区别如表3-1所示。

表3-1 Java虚拟机和Dalvik虚拟机的区别