关于Dalvik,我们该知道些什么?

1,142 阅读2分钟

Dalvik和JVM的区别
Dex文件的结构
Dalvik如何加载Class

Dalvik和JVM的区别

Dalvik和JVM最主要区别是它们分别具有不同的类文件格式和指令集。Dalvik使用的是dex(Dalvik Executable)格式的类文件,而Java虚拟机使用的是class格式的类文件。

Dalvik的指令是基于寄存器的,而JVM的指令是基于堆栈的,因此Dalvik需要更多的指令空间。这样的区别其实各有优劣,JVM需要占用更多的CPU时间,而Dalvik的数据缓冲更容易失效。

Dex文件结构

先看一张Class文件和Dex文件对比图:

Dex这么设计可以使文件更紧凑,减少拢余,还可以共享资源,进而减少文件大小。

各个字段含义如下:

数据名称 解释
header Dex文件头部,记录整个Dex文件的相关属性
string_ids 字符串数据索引,记录了每个字符串在数据区的偏移量
type_ids 类似数据索引,记录了每个类型的字符串索引
proto_ids 原型数据索引,记录了方法声明的字符串,返回类型字符串,参数列表
field_ids 字段数据索引,记录了所属类、类型以及方法名
method_ids 类方法索引,记录方法所属类名、方法声明以及方法名等信息
class_defs 类定义数据索引,记录指定类各类信息,包括接口,超类,类数据偏移量
data 数据区,保存了各个类的真实数据
link_data 链接数据区

Dalvik如何加载Class

解析Dex

加载之前需要有一个解析过程,Dex文件大体可以分为三大部分:头部、索引、数据。通过头部可以找到索引的数目、位置和数据的起始位置。然后,Dalvik会调用dexFileParse函数对它进行分析,分析的结果放到DexFile数据结构中。

加载Dex

存储的数据结构如下:

typedef struct Object {
    ClassObject* clazz;  // 类型对象
    Lock lock;           // 锁对象
} Object;

clazz指向ClassObject对象,里面还包含一个Lock对象。如果其它线程想要获取它的锁,只有等当前线程释放掉才可以。

从Dex数据区读取过程中,会在内存中分配几个内存区域,用于存放directMethod、virtualMethod、sfield、ifield。等得到索引后,加载实际是由loadClassFromDex完成,它首先会先读取class的具体信息,再加载directMethod、virtualMethod、sfield、ifield,然后会为ClassObject数据结构分配内存,并读取Dex文件相关信息。等加载完成后,将加载的class放入哈希表中方便下次快速查找。