Class文件
Class文件是Java虛擬機定義并被其所識別的文件格式,通俗地講,每一個接口或者類對應一個Class文件。
Class文件格式
- Class文件是一組以8位字節為基礎單位的的二進制流。
- 各數據項目之間沒有任何分隔符
- Class文件格式采用的結構只有兩種數據結構:無符號數和表。
- 無符號數:以u1,u2等表示1,2個字節的無符號數,無符號數可用于描述數字、索引引用、數量值、字符串值。
- 表:以多個無符號數或者表組成,通常以_info結尾,整個Class文件就是一張表。
Class文件的組成:
Class文件結構
- 魔數:Class文件開始四個字節是魔數,用于驗證該文件是否能被虛擬機執行
- 版本號:魔數后四個字節則是Class文件的主版本號和次版本號
- 常量池:版本號后面緊跟著的則是常量池部分。常量池不同與java中,它是由1開始計數的,常量癡表的數目是常量個數減一。第0項為保留項目,用于指示當前Class文件不需要引用任何一個常量池。常量池中主要包含兩大類常量:
- 字面量:包括文本字符串,被聲明為final的常量值等。
- 符號引用:包括類和接口的權限定名,字段的名稱和描述符,方法的名稱和描述符
- 訪問標志:常量池部分結束后則是訪問標志部分,該部分包括信息:是類還是接口,是否定義為public,是否final,是否abstract等信息。
- 訪問標志之后則是類索引,父類索引,接口索引集合部分,該部分的主要信息為:該類的信息的索引,父類的信息的索引,實現接口的個數和對應接口信息的索引。(通過指向一個類型為CONSTANT_Class_info的類描述符常量,從而在對應的常量池找到相關信息)
- 字段表:接下來的部分則是用于描述類聲明的變量信息,包括變量的作用域,是否為static,是否為final等信息。
- 方法表:方法表則是用于描述類中方法的信息,與字段表類似。
- 屬性表:屬性表在字段表和方法表中都會出現,主要用于描述某些場景特有的信息。比如方法是否拋出異常,被final聲明的變量的值,內部類列表等信息。
Dex文件
Dex是Android平臺上(Dalvik虛擬機,art虛擬機)的可執行文件,每個APK壓縮包中都包含一個(或者多個MultiDex)Dex文件,Dex文件中包含了app的所有源碼。
Dex文件的結構
- Dex文件是一組以8位字節為基礎單位的的二進制流。
- Dex文件的各數據項目之間也沒有任何分隔符
-
Dex文件由文件頭,索引區,數據區三個部分組成
Dex文件結構 - 其各個元素的解釋如下:
- header:dex文件頭部,記錄整個dex文件的相關屬性
- string_ids:字符串數據索引,記錄了每個字符串在數據區的偏移量
- type_ids:類型數據索引,記錄了每個類型的字符串索引
- proto_ids:原型數據索引,記錄了方法聲明的字符串,返回類型字符串,參數列表
- field_ids:字段數據索引,記錄了所屬類,類型以及方法名
- method_ids:類方法索引,記錄方法所屬類名,方法聲明以及方法名等信息
- class_defs:類定義數據索引,記錄指定類各類信息,包括接口,超類,類數據偏移量
- data:數據區,保存了各個類的真實數據
- link_data:連接數據區
header
文件頭記錄了dex文件的一些基本信息, 以及大致的數據分布。其各字段及解釋如下:
索引區
索引區中索引了整個dex中的字符串、類型、方法聲明、字段以及方法的信息, 其結構體的開始位置和個數均來自dex文件頭中的記錄
- 字符串索引區:描述dex文件中所有的字符串信息
- 類型索引區:描述dex文件中所有的類型, 如類類型、基本類型、返回值類型等
- 方法聲明索引區:描述dex文件中所有的方法聲明
- 字段索引區:描述dex文件中所有的字段聲明, 這個結構中的數據全部都是索引值, 指明了字段所在的類、字段的類型以及字段名稱
- 方法索引區:描述Dex文件中所有的方法, 指明了方法所在的類、方法的聲明以及方法名字
數據區
索引區中的最終數據偏移以及文件頭中描述的偏移都指向數據區, 還包括了即將要解析的class_def_item
- class_def_item:這個結構由dex文件頭中的classDefsSize和classDefsOff所指向, 描述Dex文件中所有類定義信息, 每一個DexClassDef中包含一個DexClassData的結構(classDataOff),每一個DexClassData中包含了一個Class的數據, Class數據中包含了所有的方法, 方法中包含了該方法中的所有指令
Class文件和Dex文件對比
- Class文件是JVM的執行文件,而Dex文件是安卓虛擬機(Dalvik,art)的執行文件
- Class文件對應Java中每一個類,而Dex文件則包含整個APK文件中的JAVA代碼,故Dex文件可以大大縮小體積,減少Class文件的數據冗余,有利于在移動端中運行。(可以通過SDK中的dx命令將若干個Class文件轉化為Dex文件)