1. Dalvik 虚拟机
Dalvik 虚拟机(Dalvik Virtual Machine),简称 Dalvik VM 或者 DVM。它是 Google 专门为 Android 平台开发的虚拟机,运行在 Android 运行时库中。DVM 并不是一个 Java 虚拟机,原因如下。
1.1 DVM 与 JVM 的区别
DVM 没有遵循 JVM 规范来实现,与 JVM 主要区别如下:
1. 基于的架构不同
JVM 的执行的指令是基于栈结构,这就意味着需要去栈中读写数据,所需的指令会很多,会导致速度变慢,对于性能有限的移动设备,显然不合适。DVM 是基于寄存器的,没有基于栈的虚拟机在复制数据时使用的大量的出入栈指令,同时指令更紧凑、更简介。但是由于指定了操作数,所以指令会比基于栈的指令大,但是由于指令数量的减少,总的代码不会增加多少。
2. 执行的字节码不同
在 Java SE 程序中,Java 类被编译成一个或多个 .class 文件,并打包成 jar 文件,而后 JVM 会通过相应的 .class 文件和 jar 文件获取对相应的字节码。执行顺序为:.java 文件 → .class 文件 → .jar 文件,而 DVM 会用 dx 工具将所有的 .class 文件转换为一个 .dex 文件,然后 DVM 会从该 .dex 文件读取指令和数据。执行顺序为:.java 文件 → .class 文件 → .dex 文件。
jar 文件和 apk 文件结构如图:

文件结构对比图
当 JVM 加载 .jar 文件的时候,会加载里面所有的 .class 文件,这种加载方式对于性能有限的移动设备不合适。在 .apk 文件中,一般情况下只包含一个 .dex 文件,这个 .dex 文件把所有的 .class 文件信息整合在一起,这样就提升了加载速度。.class 文件种也会存在一些冗余信息,dex 工具会去除冗余信息,并把所有的 .class 文件整合到 .dex 文件种,减少 I/O 操作,加快了类的查找速度。
3. DVM 允许在有限的内存中同时运行多个进程
DVM 经过优化,允许在有限的内存中同时运行多个进程。在 Android 中的每一个应用都运行在一个 DVM 实例中,每一个 DVM 实例都运行在一个独立的进程空间中,独立的进程可以防止在虚拟机崩溃的时候所有的程序都关闭。
4. DVM 由 Zygote 创建和初始化
Zygote 是第一个 DVM 进程,同时也用来创建和初始化 DVM 实例。每当系统需要创建一个应用程序时,Zygote 就会 fork 自身,快速的创建和初始化一个 DVM 实例,用于应用程序的运行。对于一些只读的系统库,所有的 DVM 实例都会和 Zygote 共享一块内存区域,节省了内存开销。
5. DVM 有共享机制
DVM 拥有预加载——共享的机制,不同的应用之间在运行时可以共享相同的类,拥有更高的效率。而 JVM 不存在这种共享机制,不同的程序,打包后彼此独立,即便它们使用了同样的类,运行时也都是单独加载和运行的,无法进行共享。
6. DVM 早期没有使用 JIT 编译器
早期的 DVM 没有使用 JIT 编译器,每次执行代码,都需要通过解释器将 dex 代码编译成机器码,然后执行,效率不高。为了解决这一问题,从 Android 2.2 版本开始 DVM 使用了 JIT 编译器,它会对多次运行的代码(热点代码)进行编译,生成精简的本地机器码(Native Code),这样在下次执行到相同代码时,可以

本文详细介绍了Android的Dalvik虚拟机和ART运行时的区别与工作原理。Dalvik基于寄存器架构,使用dex文件,允许进程间共享,由Zygote创建初始化,并采用标记-清除GC。而ART则引入了预编译(AOT)、64位支持和改进的垃圾回收机制,提高了运行效率。ART的运行时堆采用多种GC方案,提供更优的性能体验。


被折叠的 条评论
为什么被折叠?



