Class文件
Class文件是Java虛擬機(jī)定義并被其所識(shí)別的文件格式,通俗地講窄锅,每一個(gè)接口或者類對(duì)應(yīng)一個(gè)Class文件钦勘。
Class文件格式
- Class文件是一組以8位字節(jié)為基礎(chǔ)單位的的二進(jìn)制流。
- 各數(shù)據(jù)項(xiàng)目之間沒有任何分隔符
- Class文件格式采用的結(jié)構(gòu)只有兩種數(shù)據(jù)結(jié)構(gòu):無符號(hào)數(shù)和表谭企。
- 無符號(hào)數(shù):以u(píng)1,u2等表示1倔毙,2個(gè)字節(jié)的無符號(hào)數(shù)壶栋,無符號(hào)數(shù)可用于描述數(shù)字、索引引用普监、數(shù)量值、字符串值。
- 表:以多個(gè)無符號(hào)數(shù)或者表組成凯正,通常以_info結(jié)尾毙玻,整個(gè)Class文件就是一張表。
Class文件的組成:
Class文件結(jié)構(gòu)
- 魔數(shù):Class文件開始四個(gè)字節(jié)是魔數(shù)廊散,用于驗(yàn)證該文件是否能被虛擬機(jī)執(zhí)行
- 版本號(hào):魔數(shù)后四個(gè)字節(jié)則是Class文件的主版本號(hào)和次版本號(hào)
- 常量池:版本號(hào)后面緊跟著的則是常量池部分桑滩。常量池不同與java中,它是由1開始計(jì)數(shù)的允睹,常量癡表的數(shù)目是常量個(gè)數(shù)減一运准。第0項(xiàng)為保留項(xiàng)目,用于指示當(dāng)前Class文件不需要引用任何一個(gè)常量池缭受。常量池中主要包含兩大類常量:
- 字面量:包括文本字符串胁澳,被聲明為final的常量值等。
- 符號(hào)引用:包括類和接口的權(quán)限定名米者,字段的名稱和描述符韭畸,方法的名稱和描述符
- 訪問標(biāo)志:常量池部分結(jié)束后則是訪問標(biāo)志部分,該部分包括信息:是類還是接口蔓搞,是否定義為public胰丁,是否final,是否abstract等信息喂分。
- 訪問標(biāo)志之后則是類索引锦庸,父類索引,接口索引集合部分蒲祈,該部分的主要信息為:該類的信息的索引甘萧,父類的信息的索引,實(shí)現(xiàn)接口的個(gè)數(shù)和對(duì)應(yīng)接口信息的索引讳嘱。(通過指向一個(gè)類型為CONSTANT_Class_info的類描述符常量幔嗦,從而在對(duì)應(yīng)的常量池找到相關(guān)信息)
- 字段表:接下來的部分則是用于描述類聲明的變量信息,包括變量的作用域沥潭,是否為static邀泉,是否為final等信息。
- 方法表:方法表則是用于描述類中方法的信息钝鸽,與字段表類似汇恤。
- 屬性表:屬性表在字段表和方法表中都會(huì)出現(xiàn),主要用于描述某些場(chǎng)景特有的信息拔恰。比如方法是否拋出異常因谎,被final聲明的變量的值,內(nèi)部類列表等信息颜懊。
Dex文件
Dex是Android平臺(tái)上(Dalvik虛擬機(jī)财岔,art虛擬機(jī))的可執(zhí)行文件风皿,每個(gè)APK壓縮包中都包含一個(gè)(或者多個(gè)MultiDex)Dex文件,Dex文件中包含了app的所有源碼匠璧。
Dex文件的結(jié)構(gòu)
- Dex文件是一組以8位字節(jié)為基礎(chǔ)單位的的二進(jìn)制流桐款。
- Dex文件的各數(shù)據(jù)項(xiàng)目之間也沒有任何分隔符
-
Dex文件由文件頭,索引區(qū)夷恍,數(shù)據(jù)區(qū)三個(gè)部分組成
Dex文件結(jié)構(gòu) - 其各個(gè)元素的解釋如下:
- header:dex文件頭部魔眨,記錄整個(gè)dex文件的相關(guān)屬性
- string_ids:字符串?dāng)?shù)據(jù)索引,記錄了每個(gè)字符串在數(shù)據(jù)區(qū)的偏移量
- type_ids:類型數(shù)據(jù)索引酿雪,記錄了每個(gè)類型的字符串索引
- proto_ids:原型數(shù)據(jù)索引遏暴,記錄了方法聲明的字符串,返回類型字符串指黎,參數(shù)列表
- field_ids:字段數(shù)據(jù)索引朋凉,記錄了所屬類,類型以及方法名
- method_ids:類方法索引袋励,記錄方法所屬類名侥啤,方法聲明以及方法名等信息
- class_defs:類定義數(shù)據(jù)索引,記錄指定類各類信息茬故,包括接口盖灸,超類,類數(shù)據(jù)偏移量
- data:數(shù)據(jù)區(qū)磺芭,保存了各個(gè)類的真實(shí)數(shù)據(jù)
- link_data:連接數(shù)據(jù)區(qū)
header
文件頭記錄了dex文件的一些基本信息, 以及大致的數(shù)據(jù)分布赁炎。其各字段及解釋如下:
索引區(qū)
索引區(qū)中索引了整個(gè)dex中的字符串、類型钾腺、方法聲明徙垫、字段以及方法的信息, 其結(jié)構(gòu)體的開始位置和個(gè)數(shù)均來自dex文件頭中的記錄
- 字符串索引區(qū):描述dex文件中所有的字符串信息
- 類型索引區(qū):描述dex文件中所有的類型, 如類類型、基本類型放棒、返回值類型等
- 方法聲明索引區(qū):描述dex文件中所有的方法聲明
- 字段索引區(qū):描述dex文件中所有的字段聲明, 這個(gè)結(jié)構(gòu)中的數(shù)據(jù)全部都是索引值, 指明了字段所在的類姻报、字段的類型以及字段名稱
- 方法索引區(qū):描述Dex文件中所有的方法, 指明了方法所在的類、方法的聲明以及方法名字
數(shù)據(jù)區(qū)
索引區(qū)中的最終數(shù)據(jù)偏移以及文件頭中描述的偏移都指向數(shù)據(jù)區(qū), 還包括了即將要解析的class_def_item
- class_def_item:這個(gè)結(jié)構(gòu)由dex文件頭中的classDefsSize和classDefsOff所指向, 描述Dex文件中所有類定義信息, 每一個(gè)DexClassDef中包含一個(gè)DexClassData的結(jié)構(gòu)(classDataOff),每一個(gè)DexClassData中包含了一個(gè)Class的數(shù)據(jù), Class數(shù)據(jù)中包含了所有的方法, 方法中包含了該方法中的所有指令
Class文件和Dex文件對(duì)比
- Class文件是JVM的執(zhí)行文件间螟,而Dex文件是安卓虛擬機(jī)(Dalvik吴旋,art)的執(zhí)行文件
- Class文件對(duì)應(yīng)Java中每一個(gè)類,而Dex文件則包含整個(gè)APK文件中的JAVA代碼厢破,故Dex文件可以大大縮小體積荣瑟,減少Class文件的數(shù)據(jù)冗余,有利于在移動(dòng)端中運(yùn)行摩泪。(可以通過SDK中的dx命令將若干個(gè)Class文件轉(zhuǎn)化為Dex文件)