一、Dalvik 虚拟机
Dalvik
是Google
公司自己设计用于Android
平台的Java
虚拟机,它是Android
平台的重要组成部分,支持dex
格式的Java
应用程序的运行。
Dalvik
作为面向Linux
、为嵌入式操作系统设计的虚拟机,主要负责完成 对象生命周期管理、堆栈管理、线程管理、安全和异常管理,以及垃圾回收等。Dalvik
充分利用Linux
进程管理的特定,对其进行了面向对象的设计,使得可以 同时运行多个进程,而传统的Java
程序通常只能运行一个进程。
1.1 Dalvik 虚拟机和 JVM 的对比
区别一
- 大多数的
JVM
虚拟机基于 栈的结构,基于栈的指令更紧凑,使用的指令只占用一个字节,因而成为字节码。 - 而
Dalvik
虚拟机则是基于 寄存器,基于寄存器的指令由于需要指定源地址和目标地址,因此需要占用更多的指令空间,某些指令需要占用两个字节。
区别二
-
Java
虚拟机运行的是Java
字节码。Java
类会被编译成一个或者多个.class
文件,然后打包到jar
文件中,接着Java
虚拟机会从相应的.class
文件和.jar
文件中获取对应的字节码。 -
Dalvik
虚拟机运行的是.dex
文件。在Java
类被编译成.class
文件后,还会通过dx
工具将所有的.class
文件转换一个.dex
文件,Dalvik
虚拟机再从中读取指令和数据。.dex
文件除了减少整体的文件尺寸和I/O
操作次数,也提高了类的查找速度。
区别三
-
class
文件中包含多个不同的方法签名,如果A
类文件引用B
类文件中的方法,方法签名也会被复制到A
类文件中(在虚拟机加载类的连接阶段将会使用该签名链接到B
类的对应方法),也就是说,多个不同的类会同时包含相同的方法签名,同样地,大量的字符串常量在多个类文件中也被重复使用,这些冗余信息会直接增加文件的体积,而JVM
在把描述类的数据从.class
文件加载到内存时,需要对数据进行校验、转换解析和初始化,最终才形成可以被虚拟机直接使用的JAVA
类型,因为大量的冗余信息,会严重影响虚拟机解析文件的效率。 - 在
.dex
文件中,由于dx
工具会对JAVA
类文件重新排列,将所有JAVA
类文件中的常量池分解,消除其中的冗余信息,重新组合形成一个常量池,所有的类文件共享同一个常量池,使得相同的字符串、常量在.dex
文件中只出现一次,从而减小了文件的体积。
1.2 Dalvik 虚拟机特点
- 使用
dex
格式的字节码,不兼容Java
字节码格式 - 代码密度小,运行效率高,节省资源
- 常量池只使用
32
位的索引 - 有内存限制
- 默认栈大小是
12KB
- 堆默认启动大小为
2MB
,默认最大值为16MB
- 堆支持的最小启动大小为
1MB
,支持的最大值为1024MB
- 堆和栈参数可以通过
-Xms
和-Xmx
修改
1.3 Dalvik 系统架构
1.3.1 dex 文件结构
.dex
文件结构和.class
文件结构差异的地方很多,但从携带的信息上看,.dex
和.class
文件是一致的:
-
header
:存储了各个数据类型的起始地址、偏移量等信息。 -
proto_ids
:描述函数原型信息,包括返回值,参数信息。比如“test:()V”
-
methods_ids
:函数信息,包括所属类及对应的proto
信息。
虽然.dex
文件的结构很紧凑,但想要运行时的性能得到进一步提升,还需要对dex
文件进行进一步优化。优化主要针对以下几个方面:
- 调整所有字段的字节序和对齐结构中的每一个域
- 验证
.dex
文件中的所有类 - 对一些特定的类进行优化,对方法里的操作码进行优化
.dex
文件经过优化后文件大小会膨胀,大约增加到原来的1~4
倍。对于内置应用,一般在系统编译后,便会生成优化文件odex(Optimized dex)
。一个Android
应用程序,需要经过以下过程才可以在Dalvik
虚拟机上运行:
- 把
Java
源文件编译成.class
文件 - 使用
dx
工具把.class
文件转换成.dex
文件 - 使用
aapt
工具把.dex
文件、资源文件以及AndroidManifest.xml
文件组合成APK - 将
APK
安装到Android
设备运行
1.3.2 Dalvik 类加载器
一个dex
文件需要类加载器加载原生类和Java
类,然后通过解释器根据指令集对Dalvik
字节码进行解释和执行。Dalvik
类加载器使用mmap
函数,将dex
文件映射到内存中,通过普通的内存读取操作即可访问dex
文件,然后解析dex
文件内容并加载其中的类到哈希表中。
解析 dex
总的来说,dex
文件可以抽象为三个部分:头部、索引、数据。通过头部可以知道索引的位置和数目,以及数据区的起始位置。将dex
文件映射到内存后,Dalvik
会调用dexFileParse
函数对其进行分析,分析的结果放到DexFile
数据结构中。DexFile
中的baseAddr
指向映射区的起始位置,pClassDefs
指向class
索引的起始位置。为了加快class
的查找速度,还创建一个哈希表,对class
名字进行哈希并生成索引。
加载 class
解析工作完成后就进行class的加载,加载的类需要用ClassObject
数据结构来存储。
typedef struct Object {
ClassObject* clazz; // 类型对象
Lock lock; // 锁对象
} Object;
其中clazz
指向ClassObjec
t对象,还包含一个Lock
对象。如果其它线程想要获取它的锁,只有等这个线程释放。Dalvik
每加载一个class
都会对应一个ClassObject
对象,加载过程会在内存中分配几个区域,分别存放directMethod
、virtualMethod
、sfield
、ifield
。这些信息从dex
文件的数据区中读取。字段Field
的定义如下:
struct Field {
ClassObject* clazz; //所属类型
const char* name; // 变量名称
const char* signature; // 如“Landroid/os/Debug;”
u4 accessFlags; // 访问标记
#ifdef PROFILE_FIELD_ACCESS
u4 gets;
u4 puts;
#endif
};
待得到class
索引后,实际的加载由loadClassFromDex
来完成。首先它会读取class
的具体数据,分别加载directMethod
、virtualMethod
、ifield
和sfield
,然后为ClassObject
数据结构分配内存,并读取dex
文件的相关信息。加载完成后,将加载的class
通过dvmAddClassToHash
函数放入哈希表,以方便下次查找;最后,通过dvmLinkClass
查找该类的超类,如果有接口类则加载相应的接口类。
1.3.3 Dalvik 解释器
对于任何虚拟机来说,解释器无疑是核心的部分,所有的Java
字节码都经过解释器解释执行。由于Dalvik
解释器的效率很重要,Android
分别实现了C
语言版和各种汇编语言版的解释器。解释器通常是循环执行,需要一个入口函数调用处理程序执行第一条指令,而后每条指令执行时引出下一条指令,通过函数指针调用处理程序。
二、Dalvik 虚拟机和 ART 虚拟机对比
在Android 4.4
之后,Google
开始使用了更加优秀的ART
虚拟机来替换Dalvik
虚拟机,下面我们就来对比一下这两者之间的区别。
2.1 Dalvik
在 打包的过程中 会先将.java
等源码通过javac
编译成.class
文件,再通过dx
将.class
文件转换成Dalvik
虚拟机执行的.dex
文件。
在 应用启动的时候 先将.dex
文件 转换成机器码,又因为65536
的文件,导致在应用冷启动的时候有一个合包的过程,最后的结果就是app
的启动时间有可能变慢,这就是Dalvik
虚拟机的JIT(Just in Time)
特性。
2.2 ART
ART
除了兼容了Dalvik
虚拟机的特性之外,还有一个很好的特性AOT(Ahead of Time)
,这个特性就是把 .dex 文件转换成机器码 这个步骤提前到了 应用安装 的时候,ART
虚拟机将.dex
文件转换成可直接运行的.oat
文件,ART
虚拟机天生支持多dex
,所以也不会有一个合包的过程,因此会极大的提升APP
冷启动速度。
2.3 ART 虚拟机的优缺点
优点:
- 加快
APP
冷启动速度 - 提升
GC
速度 - 提供功能全面的
Debug
特性
缺点:
-
APP
安装速度慢,因为在APK
安装的时候要生成可运行.oat
文件 -
APK
占用空间大,因为在APK
安装的时候要生成可运行.oat
文件
三、参考文献
理解 Android 虚拟机体系结构
Android Dalvik 虚拟机和 ART 虚拟机对比
Dalvik 虚拟机简要介绍和学习计划
Dalvik 虚拟机的启动过程分析
Dalvik 虚拟机的运行过程分析
深入理解 Dalvik 虚拟机 - Android应用进程启动过程分析
深入理解 ART 虚拟机 - 虚拟机的启动
深入理解 ART 虚拟机 - ART 的函数运行机制
深入理解 Dalvik 虚拟机 - 解释器的运行机制
深入理解ART虚拟机 - ImageSpace的加载过程分析
更多文章,欢迎访问我的 Android 知识梳理系列:
- Android 知识梳理目录:http://www.jianshu.com/p/fd82d18994ce
- Android 面试文档分享:http://www.jianshu.com/p/8456fe6b27c4