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放入哈希表中方便下次快速查找。