对于Android应用层开发,底层虚拟机知识除了JVM之外,还应对Dalvik和ART有所了解,涉及的知识不多,在此进行一下归纳总结
Dalvik
1. DVM与JVM的区别
DVM之所以不是JVM,是因为其并未遵守JVM规范来实现,因此主要有以下区别
-
基于的架构不同:JVM基于栈,读写数据时需要更多的指令,即代表速度会因此降低,对于性能有限的移动设备不太合适。DVM基于寄存器,不像JVM需要频繁的出栈入栈指令,因此指令更少更简洁,但与此同时也显示制定了操作数,所以指令会比JVM中要大,总的代码数不会增加多少
-
执行的字节码不同:Java会被JVM编译为一个或多个".class"文件,最后打包为jar包。而Java在DVM中,会通过dx工具将所有的".class"文件转换为一个dex文件,打包为aar包。我们都知道“.jar"文件里会包含多个".class"文件,加载时需要把他们全部加载。而“.apk”文件只包含一个“.dex”文件,整合了所有".class"文件的信息,上面提到的dex工具会剔除冗余信息,减少IO操作,加快了类的加载速度
image.png -
DVM允许在有限内存中同时运行多个进程:DVM经过优化,允许在有限内存中同时运行多个进程。每一个app都运行在一个DVM实例中,而每一个DVM实例都运行在一个独立的进程空间,独立的进程空间可以防止虚拟机崩溃时所有程序都被关闭
image.png
-
DVM由Zygote创建和初始化:Zygote就是一个DVM进程,同时也用于创建和初始化DVM实例,系统需要创建一个应用程序时,Zygote就会fork自身,快速创建。所有的DVM实例都会和Zygote共享一块内存区域,节省开销
-
DVM共享机制:DVM拥有预加载——共享机制,不同应用程序之间在运行时可以共享相同的类,拥有更高效率,而JVM打包后程序彼此独立,不存在这种共享机制
-
DVM早期没有使用JIT编译器:JVM使用了JIT编译器,即时编译器,而DVM早期没有使用,因此每次执行代码都需要通过解释器将dex代码编译为机器码,交给系统,效率很低。之后DVM加入了JIT,对热点代码进行编译后生成精简的本地机器码,下一次运行到热点代码时不需要编译,直接运行。需要注意的是,应用程序每次重新运行时都要重做编译工作,因此每次打开应用程序,都需要JIT编译
2. DVM架构
DVM源码部分 目录 / 文件 说明如下
-
dexdump:生成dex文件的反编译查看工具,用于查看编译出来的代码的正确性和结构
-
dexgen:dex代码生成器项目
-
docs:DVM文档
-
dx:Java字节码转换为DVM机器码工具
-
libdex:生成主机和设备处理dex文件的库
-
tools:一些反编译和运行相关工具
-
Android.mk:虚拟机编译的makefile配置文件
-
MODULE_LICENSE_APACHE2:APACHE2版权文件
-
NOTICE:虚拟机源码版权
其中,libdex会被编译为libdex.a静态库,作为dex工具使用。dexdump是反编译工具。DVM架构如图所示
image.png
3. DVM运行时堆
DVM运行时堆使用标记——清除算法进行GC,主要结构如下
image.png
ART
ART虚拟机的发布是用来替换DVM的,先来看ART和DVM的区别
1. ART与DVM的区别
-
AOT机制:ART中,系统在安装应用程序时会进行一次预编译,将字节码预先编译为机器码存储在本地,这样每次运行时都不用再次编译了,效率大大提升,ART中也加入了JIT作为AOT的补充,协同工作
-
兼容性:DVM为32位cpu设计,而ART支持64位并且兼容32位cpu
-
回收优化:ART对垃圾回收机制进行了改进,比如更频繁的进行垃圾收集,减少GC暂停等
-
空间划分:ART运行时堆空间划分和DVM不同
2. ART运行时堆
与DVM的GC不同的是,ART采用了多种垃圾回收方案,每个方案会运行不同的垃圾收集器,默认采用了CMS方案,该方案主要使用sticky-CMS和partial-CMS。根据不同的方案,运行时堆也有不同的划分,默认由4个Space和多个辅助数据结构组成,具体如图
image.png
网友评论