Dalvik
Dalvik 虚拟机(Dalvik Virtual Machine),简称 Dalvik VM 或者 DVM。它是 Google 专门为 Android 平台开发的虚拟机,运行在 Android 运行时库中。
JVM与DVM
DVM 不是一个严格意义上的 JVM,主要原因是 DVM 并没有遵循 JVM 规范来实现,与 JVM 主要区别如下:
基于的架构不同
JVM 的执行的指令是基于栈结构,这就意味着需要去栈中读写数据,所需的指令会很多,会导致速度变慢,对于性能有限的移动设备,显然不合适。
DVM 是基于寄存器的,没有基于栈的虚拟机在复制数据时使用的大量的出入栈指令,同时指令更紧凑、更简介。但是由于指定了操作数,所以指令会比基于栈的指令大,但是由于指令数量的减少,总的代码不会增加多少。
执行的字节码不同
jvm通过解码class文件来运行程序;dvm则是dex文件。
当 JVM 加载 .jar 文件的时候,会加载里面所有的 .class 文件,这种加载方式对于性能有限的移动设备不合适。在 .apk 文件中,一般情况下只包含一个 .dex 文件,这个 .dex 文件把所有的 .class 文件信息整合在一起,这样就提升了加载速度。.class 文件种也会存在一些冗余信息,dex 工具会去除冗余信息,并把所有的 .class 文件整合到 .dex 文件种,减少 I/O 操作,加快了类的查找速度。
DVM 允许在有限的内存中同时运行多个进程
DVM 经过优化,允许在有限的内存中同时运行多个进程。在 Android 中的每一个应用都运行在一个 DVM 实例中,每一个 DVM 实例都运行在一个独立的进程空间中,独立的进程可以防止在虚拟机崩溃的时候所有的程序都关闭。
DVM 由 Zygote 创建和初始化
Zygote 是第一个 DVM 进程,同时也用来创建和初始化 DVM 实例。每当系统需要创建一个应用程序时,Zygote 就会 fork 自身,快速的创建和初始化一个 DVM 实例,用于应用程序的运行。对于一些只读的系统库,所有的 DVM 实例都会和 Zygote 共享一块内存区域,节省了内存开销。
JIT 编译器
从 Android 2.2 版本开始 DVM 使用了 JIT 编译器,它会对多次运行的代码(热点代码)进行编译,生成精简的本地机器码(Native Code),这样在下次执行到相同代码时,可以直接使用机器码执行。但是,应用程序每次重新运行时,都需要做 JIT 编译工作。
ART
ART(Android Runtime)虚拟机是 Android 4.4 发布的,用来替换 Dalvik 虚拟机,Android 4.4 默认采用 DVM,但是可以选择使用 ART。在 Android 5.0 版本中默认使用 ART,DVM 从此退出历史舞台。
AOT预编译
DVM 中的应用每次运行时,字节码搜需要通过 JIT 编译器编译成机器码,这会使得应用程序的运行效率降低。而在 ART 中,系统在安装应用程序时会进行一次 AOT(ahead of time compilation, 预编译),将字节码预先编译成机器码并存储在本地,这样应用程序每次运行时就不需要执行编译了,运行 效率会大大提升,设备的耗电量也会降低。
不过采用 AOT 也有缺点
AOT 会使得应用程序的安装时间变长,尤其是一些复杂的应用
字节码预先编译成机器码,机器码需要的存储空间会多一些
为了弥补以上两个缺点,Android 7.0 版本的 ART 加入了即时编译器 JIT,作为 AOT 的一个补充,在应用程序安装时不会将字节码全部编译成机器码,而是在运行种将热点代码编译成机器码,从而缩短了应用程序的安装时间并节省了存储空间。
ART 与 DVM
DVM 使用JIT,ART使用AOT+JIT(具体看上一小节)
DVM 时为 32 位 CPU 设计的,而 ART 支持 64 位并兼容 32 位 CPU,这也是 DVM 被淘汰的主要原因之一。
ART 对垃圾回收机制进行了改进,比如更频繁地执行并行垃圾收集,将 GC 暂停由 2 次减少为 1 次等。
ART 的运行时堆空间划分与 DVM 不同。
网友评论