Dex文件的了解分析

什么是dex文件

他是Android系統(tǒng)的可執(zhí)行文件,包含應(yīng)用程序的全部操作指令以及運(yùn)行時(shí)數(shù)據(jù)舆乔。

由于dalvik是一種針對嵌入式設(shè)備而特殊設(shè)計(jì)的java虛擬機(jī)岳服,所以dex文件與標(biāo)準(zhǔn)的class文件在結(jié)構(gòu)設(shè)計(jì)上有著本質(zhì)的區(qū)別

當(dāng)java程序編譯成class后,還需要使用dx工具將所有的class文件整合到一個(gè)dex文件希俩,目的是其中各個(gè)類能夠共享數(shù)據(jù)练般,在一定程度上降低了冗余煌往,同時(shí)也是文件結(jié)構(gòu)更加經(jīng)湊绿店,實(shí)驗(yàn)表明拙寡,dex文件是傳統(tǒng)jar文件大小的50%左右


下面來剖析一個(gè)類文件編譯后生成的dex文件,看看具體有哪些東西鳞上。

使用軟件:

16近制查看器 ?010Editor

java編輯器

在開始前首先需要了解下dex文件包含的大體內(nèi)容:



java文件編譯成dex文件

編寫一個(gè)簡單的Java類这吻,命名為HelloWorld.class 然后將其編譯成dex文件:打開命令行,進(jìn)入 HelloWorld.class 所在文件夾下篙议,執(zhí)行命令:

javacHelloWorld.java

接下來會出現(xiàn)一個(gè)HelloWorld.class文件橘原,然后繼續(xù)執(zhí)行命令:

dx--dex--output=HelloWorld.dexHelloWorld.class

用010editor查看dex文件內(nèi)容

下載完成之后,我們可以用它打開dex文件了涡上,打開之后趾断,你的界面應(yīng)該是這樣的:

大體可以分為3個(gè)區(qū):三個(gè)區(qū)

那么我們來一步步分析,看下圖:

首先吩愧,我們看到 DexHeader 中每個(gè)數(shù)據(jù)前面有個(gè)u1或者u4芋酌,它們代表的意思就是 1個(gè) 或者 4個(gè) 字節(jié)的無符號數(shù)。

依次根據(jù) Header 中的數(shù)據(jù)段進(jìn)行解釋為:

magic[8]雁佳;它代表dex中的文件標(biāo)識脐帝,一般被稱為魔數(shù)。是用來識別dex這種文件的糖权,它可以判斷當(dāng)前的dex文件是否有效堵腹,可以看到它用了8個(gè)1字節(jié)的無符號數(shù)來表示,我們在010Editor中可以看到也就是“64 65 78 0A 30 33 35 00”這8個(gè)字節(jié)星澳,這些字節(jié)都是用16進(jìn)制表示的疚顷,用16進(jìn)制表示的話,兩個(gè)數(shù)代表一個(gè)字節(jié)(一個(gè)字節(jié)等于8位禁偎,一個(gè)16進(jìn)制的數(shù)能表示4位)腿堤。這8個(gè)字節(jié)用ASCII碼表轉(zhuǎn)化一下可以轉(zhuǎn)化為:dex.035(其中,'.' 不是轉(zhuǎn)化來的)如暖。目前笆檀,dex的魔數(shù)固定為dex.035

checksum;? 它是dex文件的校驗(yàn)和盒至,通過它可以判斷dex文件是否被損壞或者被篡改酗洒。它占用4個(gè)字節(jié)士修,也就是“5D 9D F9 59”。這里提醒一下樱衷,在010Editor中棋嘲,其實(shí)可以分別識別我們在DexHeader中看到的這些字段的,你可以點(diǎn)一下這里:


你可以看到這個(gè) header列表 展開了箫老,其實(shí)我們分析下來就和它這個(gè)結(jié)構(gòu)是一樣的封字,你可以先看下黔州,我們現(xiàn)在分析到了 checksum 中了耍鬓,你可以看到后面對應(yīng)的值是“59 F9 9D 5D”。咦流妻?這好像和上面的字節(jié)不是一一對應(yīng)的啊牲蜀。對的涣达,你可以發(fā)現(xiàn)它是反著寫的度苔。這是由于dex文件中采用的是小字節(jié)序的編碼方式寇窑,也就是低位上存儲的就是低字節(jié)內(nèi)容,所以它們應(yīng)該要反一下饮笛。

3.第三個(gè)到了signature[kSHA1DigestLen]了福青,signature 字段用于檢驗(yàn)dex文件素跺,其實(shí)就是把整個(gè)dex文件用SHA-1簽名得到的一個(gè)值指厌。這里占用20個(gè)字節(jié)鸥诽,你可以自己點(diǎn)010Editor看一看牡借。

4.第四個(gè)fileSize;表示整個(gè)文件的大小钠龙,占用4個(gè)字節(jié)碴里。

5.第五個(gè)headerSize;表示 DexHeader 頭結(jié)構(gòu)的大小咬腋,占用4個(gè)字節(jié)。這里可以看到它一共占用了112個(gè)字節(jié)寇壳,112對應(yīng)的16進(jìn)制數(shù)為70h壳炎,你可以選中頭文件看看010Editor是不是真的占用了這么多:

6.第6個(gè)是endianTag;代表 字節(jié)序標(biāo)記,用于指定dex運(yùn)行環(huán)境的cpu撒汉,預(yù)設(shè)值為0x12345678睬辐,對應(yīng)在101Editor中為“78 56 34 12”(小字節(jié)序)。

7.接下來兩個(gè)分別是linkSize和 u4linkOff;這兩個(gè)字段丰刊,它們分別指定了鏈接段的大小和文件偏移啄巧,通常情況下它們都為0码泛。linkSize為0的話表示靜態(tài)鏈接噪珊。

8.再下來就是mapOff字段了痢站,它指定了 DexMapList 的文件偏移搀捷,這里我們先不過多介紹它嫩舟,你可以看一下它的值為“14 04 00 00”播玖,它其實(shí)對應(yīng)的16進(jìn)制數(shù)就是414h(別忘了小字節(jié)序)蜀踏,我們可以在414h的位置看一下它在哪里:

其實(shí)就是 dex文件 最后一部分內(nèi)容。關(guān)于這部分內(nèi)容里面是什么,我們先不說钳榨,繼續(xù)往下看薛耻。

9.stringIdsSizestringIdsOff字段:這兩個(gè)字段指定了dex文件中所有用到的字符串的個(gè)數(shù)和位置偏移愤钾,我們先看stringIdsSize,它的值為:“1C 00 00 00”伙菊,16進(jìn)制的1C也就是十進(jìn)制的28,也就是說我們這個(gè)dex文件中一共有28個(gè)字符串,然后stringIdsOff為:“70 00 00 00”,代表字符串的偏移位置為70h躺坟,這下我們找到70h的地方:

這下我們就要先介紹一下DexStringId這個(gè)結(jié)構(gòu)了咪橙,圖中從70h開始,所有被選中的都是DexStringId 這種數(shù)據(jù)結(jié)構(gòu)的內(nèi)容菠剩,DexStringId 代表的是字符串的位置偏移,每個(gè)DexStringId 占用4個(gè)字節(jié),也就是說它里面存的還不是真正的字符串涧郊,它們只是存儲了真正字符串的偏移位置彤灶。

下面我們先分析幾個(gè)看看,

取第一個(gè)“B2 02 00 00”搏熄,它代表的位置偏移是2B2h暇赤,我們先找到這個(gè)位置:

可以發(fā)現(xiàn)我一共選中了10個(gè)字節(jié)鞋囊,這10個(gè)字節(jié)就表示了一個(gè)字符串译株。下面我們看一下dex文件中的字符串是如何表示的欠橘。dex中的字符串采用了一種叫做 MUTF-8 這樣的編碼,它是經(jīng)過傳統(tǒng)的UTF-8編碼修改的。在MTUF-8中棵里,它的頭部存放的是由uleb128編碼的字符的個(gè)數(shù)曙砂。(至于uleb128編碼是什么編碼截驮,這里我不詳細(xì)展開說乖菱,有興趣的可以搜索看看。)

也就是說在“08 3C 63 6C 69 6E 69 74 3E 00”這些字節(jié)中,第一個(gè)08指定的是后面需要用到的編碼的個(gè)數(shù),也就是8個(gè),即“ 3C 63 6C 69 6E 69 74 3E”這8個(gè),但是我們?yōu)槭裁匆还策x中了10個(gè)字節(jié)呢,因?yàn)樽詈笠粋€(gè)空字符“0”表示的是字符串的結(jié)尾,字符個(gè)數(shù)沒有把它算進(jìn)去。下面我們來看看“ 3C 63 6C 69 6E 69 74 3E”這8個(gè)字符代表了什么字符串:

(要說明的一點(diǎn)是练湿,這里湊巧這幾個(gè)uleb128編碼的字符都用了1個(gè)字節(jié)疾渣,所以我們可以這樣進(jìn)行查詢朱浴,uleb128編碼標(biāo)準(zhǔn)用的是1~5個(gè)字節(jié), 這里只是恰好都是一個(gè)字節(jié))廷支。也就是說上面的70h開始的第一個(gè) DexStringId 指向的其實(shí)是字符串“”(但是貌似我們的代碼中沒有用到這個(gè)字符串啊,先不用管,我們接著分析)。再看到這里:

剛剛我們分析到“B2 02 00 00”所指向的真實(shí)字符串了先壕,下面我們接著再分析一個(gè)规辱,我們直接分析第三個(gè),不分析第二個(gè)了仰猖。第三個(gè)為“C4 02 00 00”,對應(yīng)的位置也就是2C4h煮甥,我們找到它:

看這里砚偶,這就是2C4h的位置了单鹿。我們首先看第一個(gè)字符儒喊,它的值為0Bh芯义,也就是十進(jìn)制的11鬼癣,也就是說接下來的11個(gè)字符代表了它的字符串章郁,我們依舊是查看接下來11個(gè)字符代表的是什么惹悄,經(jīng)過查詢整理:

上面就是“HelloDalvik”這個(gè)字符串踩窖,可以看看我們的代碼徐矩,我們確實(shí)用了一個(gè)這樣的字符串窒百,bingo。

下面剩下的字符串就不分析了绪励。經(jīng)過整理,可以整理出我們一共用到的28個(gè)字符串為:

ok懈凹,字符串這里告一段落爬舰,下面我們繼續(xù)看DexHeader的下面的字段们陆。頭好暈~乎乎

噢,對了情屹,還不能結(jié)束呢坪仇,你現(xiàn)在可以看一下最開始發(fā)的那張dex結(jié)構(gòu)圖了:

看到了吧,我們這半天分析的 stringIdsSize 和 stringIdsOff 字段指向的位置就是上面那個(gè)箭頭指向的位置垃你,它們里面存儲的是真實(shí)字符串的位置偏移椅文,它們都存儲在data區(qū)域喂很。(先透露一下,后面我們要分析的幾個(gè)也和stringIdsSize 與 stringIdsOff 字段類似皆刺,它們里面存儲的基本都是位置偏移少辣,并不是真正的數(shù)據(jù),真正的數(shù)據(jù)都在data區(qū)域)

好羡蛾,我們繼續(xù)漓帅。

10.繼續(xù)看DexHeader圖,我們現(xiàn)在該typeIdsSizetypeIdsOff了痴怨。它們代表什么呢忙干?它們代表的是類的類型的數(shù)量和位置偏移,也是都占4個(gè)字節(jié)腿箩,下面我們看它們的值

可以看到豪直,typeIdsSize 的值為 9h,也就是我們 dex文件 中用到的類的類型一共有9個(gè)珠移,位置偏移在 E0h位置弓乙,下面我們找到這個(gè)位置

看到了吧,我選中的位置就是了钧惧。這里我們又得介紹一種數(shù)據(jù)結(jié)構(gòu)了暇韧,因?yàn)檫@里的數(shù)據(jù)也是一種數(shù)據(jù)結(jié)構(gòu)的數(shù)據(jù)組成的。那就是DexTypeId浓瞪,也就是說選中的內(nèi)容都是 DexTypeId 這種數(shù)據(jù)懈玻,這種數(shù)據(jù)結(jié)構(gòu)中只有一個(gè)變量,如下所示:

看到了吧乾颁,這就是 DexTypeId 數(shù)據(jù)結(jié)構(gòu)涂乌,它里面只有一個(gè)數(shù)據(jù)descriptorIdx,它的值的內(nèi)容是 DexStringId 列表的索引英岭。

還記得DexStringId是什么嗎湾盒?在上面我們分析字符串時(shí),字符串的偏移位置就是由 DexStringId 這種數(shù)據(jù)結(jié)構(gòu)描述的诅妹,也就是說 descriptorIdx 指向的是所有的 DexStringId 組成的列表的索引罚勾。

上面我們整理出了所有的字符串,你可以翻上去看看圖吭狡。然后我們看這里一共是9個(gè)類的類型代表的都是什么尖殃。先看第一個(gè)“05 00 00 00”,也就是05h划煮,即十進(jìn)位的5送丰。然后我們在上面所有整理出的字符串看看5索引的是什么?翻上去可以看到是“I”弛秋。接下來我們依次整理這些類的類型蚪战,也可以得到類的類型的列表

看到了吧牵现,這就是我們dex文件中所有用到的類的類型铐懊。比如“I”代表的就是int邀桑,LHelloWorld代表的就是HelloWorld,Ljava/io/PrintStream代表的就是java.io.PrintStream科乎。后面的幾個(gè)先就不說了壁畸。我們接著往下分析。

11.這下到了?protoIdsSize?和protoIdsOff了茅茂,它們代表的是dex文件中方法原型的個(gè)數(shù)和位置偏移捏萍。我們先看它們的值

如上圖就是它們的值了,protoIdsSize 的值為十進(jìn)制的7空闲,說明有7個(gè)方法原型令杈,然后位置偏移為104h,我們找到這個(gè)位置

看到了吧碴倾,這里就是了逗噩。對,下面又有新的數(shù)據(jù)結(jié)構(gòu)了跌榔。這下一個(gè)數(shù)據(jù)結(jié)構(gòu)不能滿足這塊的內(nèi)容了异雁,我們先看第一個(gè)數(shù)據(jù)結(jié)構(gòu),DexProtoId

可以看到僧须,這個(gè)數(shù)據(jù)結(jié)構(gòu)由三個(gè)變量組成纲刀。第一個(gè) shortyIdx 它指向的是我們上面分析的 DexStringId 列表的索引,代表的是方法聲明字符串担平。第二個(gè) returnTypeIdx 它指向的是 我們上邊分析的 DexTypeId 列表的索引示绊,代表的是方法返回類型字符串。第三個(gè) parametersOff 指向的是 DexTypeList 的位置索引暂论,這又是一個(gè)新的數(shù)據(jù)結(jié)構(gòu)了面褐,先說一下這里面存儲的是方法的參數(shù)列表】樟恚可以看到這三個(gè)參數(shù)盆耽,有方法聲明字符串,有返回類型扼菠,有方法的參數(shù)列表摄杂,這基本上就確定了我們一個(gè)方法的大體內(nèi)容。

我們接著看看 DexTypeList 這個(gè)數(shù)據(jù)結(jié)構(gòu)循榆,看看參數(shù)列表是如何存儲的析恢。

看到了嘛,它有兩個(gè)參數(shù)秧饮,其中第一個(gè) size 說的是 DexTypeItem 的個(gè)數(shù)映挂,那 DexTypeItem 又是啥咧泽篮?它又是一種數(shù)據(jù)結(jié)構(gòu)。我們繼續(xù)看看

恩柑船,還好帽撑,里面就一個(gè)參數(shù)。也比較簡單鞍时,就是一個(gè)指向 DexTypeId 列表的索引亏拉,也就是代表參數(shù)列表中某一個(gè)具體的參數(shù)的位置。

分析完這幾個(gè)數(shù)據(jù)結(jié)構(gòu)了逆巍,下面我們具體地分析一個(gè)類吧及塘。別走神,我們該從上圖的104h開始了锐极。

在 104h 這里笙僚,由于都是 DexProtoId 這種數(shù)據(jù)結(jié)構(gòu)的數(shù)據(jù),一個(gè) DexProtoId 一共占用12個(gè)字節(jié)灵再。所以肋层,我們?nèi)∏?2個(gè)字節(jié)進(jìn)行分析∶枢郑“06 00 00 00槽驶,00 00 00 00,94 02 00 00”鸳兽,這就是那12個(gè)字節(jié)了掂铐。首先“06 00 00 00”代表的是 shortyIdx,它的值是指向 DexStringId 列表的索引揍异,我們找到 DexStringId 列表中第6個(gè)對應(yīng)的值全陨,也就是III,說明這個(gè)方法中聲明字符串為三個(gè)int衷掷。接著辱姨,“00 00 00 00”代表的是 returnTypeIdx,它的值指向的是 DexTypeId 列表的索引戚嗅,我們找到對應(yīng)的值雨涛,也就是I,說明這個(gè)方法的返回值是int類型的懦胞。最后替久,我們看“94 02 00 00”,它代表的是 DexTypeList 的位置偏移躏尉,它的值為294h蚯根,我們找到這個(gè)位置

這里是 DexTypeList 結(jié)構(gòu),首先看前4個(gè)字節(jié)胀糜,代表的是 DexTypeItem 的個(gè)數(shù)颅拦,“02 00 00 00 ”也就是2蒂誉,說明接下來有 2個(gè)DexTypeItem 的數(shù)據(jù),每個(gè) DexTypeItem 占用2個(gè)字節(jié)距帅,也就是兩個(gè)都是“00 00”右锨,它們的值是 DexTypeId 列表的索引,我們?nèi)フ乙幌伦墩l(fā)現(xiàn)0對應(yīng)的是I陡蝇,也就是說它的兩個(gè)參數(shù)都是int型的。因此這個(gè)方法的聲明我們也就確定了哮肚。也就是int(int,int),可以看看我們的源代碼广匙,getNumber方法 確實(shí)是這樣的允趟。好,第一個(gè)方法就這樣分析完了鸦致,下面我們依舊是將這些方法的聲明整理成列表潮剪,后面可能有數(shù)據(jù)會指向它們的索引。

終于又完了一個(gè)分唾。我們準(zhǔn)備繼續(xù)下面的抗碰。累了就先去聽聽歌吧,歇一歇再看 -_-

12.fieldIdsSizefieldIdsOff字段绽乔。這兩個(gè)字段指向的是dex文件中字段名的信息弧蝇。我們看到這里

可以看到,fieldIdsSize 為3h折砸,說明共有3個(gè)字段看疗。fieldIdsOff 為158h,說明偏移為158h睦授,我們繼續(xù)看到158h這里:

咳咳两芳,又該新的數(shù)據(jù)結(jié)構(gòu)了,再忍一忍去枷,接下來的數(shù)據(jù)結(jié)構(gòu)是DexFieldId怖辆,我們看下

可以看到,這三個(gè)數(shù)據(jù)都是指向的索引值删顶,具體的就不說了竖螃,看后面的備注就是。我們依舊是分析一下第一個(gè)字段翼闹,“01 00 斑鼻,00 00,13 00 00 00”猎荠,類的類型為 DexTypeId 列表的索引1坚弱,也就是HelloWorld蜀备,字段的類型為 DexTypeId 列表中的索引0,也就是int荒叶,字段名為 DexStringId 列表中的索引13h碾阁,即十進(jìn)制的19,找一下些楣,是a脂凶,也就是說我們這個(gè)字段就確認(rèn)了,即int HelloWorld.a愁茁。這不就是我們在HelloWorld.java文件里定義的變量a嘛蚕钦。然后我們依次把我們所有的3個(gè)字段都列出來:

int HelloWorld.a

java.lang.String HelloWorld.b

java.io.PrintStream java.lang.System.out

ok,先告一段落鹅很。繼續(xù)分析下一個(gè)

13.methodIdsSizemethodIdsOff字段嘶居。這倆字段指明了方法所在的類、方法的聲明以及方法名促煮。我們看看

先是邮屁,methodIdsSize,為 Ah菠齿,即十進(jìn)制的10佑吝,說明共有10個(gè)方法。methodIdsOff绳匀,為170h芋忿,說明它們的位置偏移在170h。我們看到這里

對對對襟士,又是新的數(shù)據(jù)結(jié)構(gòu)盗飒,不過這個(gè)和上個(gè)一樣簡單,請看 DexMethodId

對吧陋桂,這個(gè)也簡單逆趣,三個(gè)數(shù)據(jù)也都是指向?qū)?yīng)的結(jié)構(gòu)的索引值。我們直接分析一下第一個(gè)數(shù)據(jù)嗜历,“01 00, 04 00宣渗, 00 00 00 00”,首先梨州,classIdx痕囱,為1,對應(yīng) DexTypeId 列表的索引1暴匠,也就是HelloWorld鞍恢;其次,protoIdx,為4帮掉,對應(yīng) DexProtoId 列表中的索引4弦悉,也就是void();最后蟆炊,nameIdx稽莉,為0,對應(yīng) DexStringId 列表中的索引0涩搓,也就是污秆。因此昧甘,第一個(gè)數(shù)據(jù)就出來了疾层,即void HelloWorld.() 将饺。后面的不進(jìn)行分析了,我們依舊是把其余的9個(gè)方法列出來

好了,這個(gè)就算分析完了湖饱。下面真正開始我們的重頭戲了。先緩一緩再繼續(xù)吧杀捻。

14.classDefsSizeclassDefsOff字段井厌。這兩個(gè)字段指明的是dex文件中類的定義的相關(guān)信息致讥。我們先找到它們的位置垢袱。

classDefsSize字段请契,為1,也就是只有一個(gè)類定義涌韩,classDefsOff氯夷,為1C0h,我們找到它的偏移位置玄捕。

這里就是了桩盲,到了這里赌结,你現(xiàn)在應(yīng)該也知道又有新的數(shù)據(jù)結(jié)構(gòu)了庄涡。對的,接下來的數(shù)據(jù)結(jié)構(gòu)是DexClassDef撕捍,請看:

不多說了忧风,我們直接根據(jù)結(jié)構(gòu)開始分析吧狮腿,反正就只有一個(gè)類定義。classIdx 為1贴硫,對應(yīng) DexTypeId 列表的索引 1夜畴,找到是HelloWorld删壮,確實(shí)是我們源程序中的類的類型。

accessFlags 為 1苞也,它是類的訪問標(biāo)志如迟,對應(yīng)的值是一個(gè)以ACC_開頭的枚舉值攻走,1對應(yīng)的是 ACC_PUBLIC昔搂,你可以在010Editor中看一下,說明我們的類是public的贤斜。

superclassIdx的值為 3瘩绒,找到DexTypeId列表中的索引3带族,對應(yīng)的是java.lang.object炉菲,說明我們的類的父類類型是Object的拍霜。interfaceOff指向的是DexTypeList結(jié)構(gòu)薪介,我們這里是0說明沒有接口汁政。如果有接口的話直接對應(yīng)到 DexTypeList记劈,就和之前我們分析的一樣了,這里不多解釋换途,有興趣的可以寫一個(gè)有接口的類驗(yàn)證下军拟。

再下來 sourceFileIdx 指向的是 DexStringId 列表的索引懈息,代表源文件名,我們這里位4怒见,找一下對應(yīng)到了字符串"HelloWorld.java"速种,說明我們類程序的源文件名為 HelloWorld.java低千。

annotationsOff 字段指向注解目錄接口示血,根據(jù)類型不同會有注解類难审、注解方法告喊、注解字段與注解參數(shù),我們這里的值為0拢切,說明沒有注解淮椰,這里也不過多解釋纳寂,有興趣可以自己試試毙芜。

接下來是 classDataOff 了爷肝,它指向的是 DexClassData 結(jié)構(gòu)的位置偏移,DexClassData 中存儲的是類的數(shù)據(jù)部分金赦,我們開始詳細(xì)分析一下它夹抗,首先漠烧,還是先找到偏移位置3F8h

接著已脓,我們看看 DexClassData 數(shù)據(jù)結(jié)構(gòu):

可以看到度液,在 DexClassData 結(jié)構(gòu)中又引入了三種結(jié)構(gòu)堕担,我們一起寫出來看一下吧

代碼中的注釋寫的也都很清楚了霹购,我們就不多說了齐疙。但是請注意,在這些結(jié)構(gòu)中的 u4 不是指的占用4個(gè)字節(jié)把将,而是指它們是 uleb128類型(占用1~5個(gè)字節(jié))的數(shù)據(jù)。關(guān)于uleb128還是不多說催训,想了解的可以自己查查看漫拭。

好混稽,接下來開始分析膳叨,對于 DexClassData菲嘴,第一個(gè)為 DexClassDataHeader龄坪,我們找到相應(yīng)的位置复唤,第一個(gè) staticFieldsSize 其實(shí)只占用了一個(gè)字節(jié)佛纫,即01h就是它的值雳旅,也就是說共有一個(gè)靜態(tài)字段攒盈,接下來 instanceFieldsSize,directMethodsSize僵蛛,virtualMethodsSize 也都是只占用了一個(gè)字節(jié)充尉,即實(shí)例字段的個(gè)數(shù)為1驼侠,直接方法的個(gè)數(shù)為3倒源,虛方法的個(gè)數(shù)為1笋熬。(這里只是湊巧它們幾個(gè)都占用一個(gè)字節(jié)腻菇,并不一定是只占用一個(gè)字節(jié),這關(guān)于到uleb128數(shù)據(jù)類型秘遏,具體可以自己了解下)垄提。

然后接下來就是 staticFields 了铡俐,它對應(yīng)的數(shù)據(jù)結(jié)構(gòu)為 DexField审丘,可以看到勾给,第一個(gè) fieldIdx播急,是指向 DexFieldId 的索引桩警,值為1捶枢,找到對應(yīng)的索引值為 java.lang.String HelloWorld.b烂叔。第二個(gè) accessFlags,值為8胯努,對應(yīng)的ACC_開頭的數(shù)據(jù)為ACC_STATIC(可以在010Editor中對應(yīng)查看一下)康聂,說明我們這個(gè)靜態(tài)字段為:static java.lang.String HelloWorld.b」嘉埃可以對應(yīng)我們的源代碼看一下导狡,我們確實(shí)定義了一個(gè)static的b變量旱捧。

接著看 instanceFields枚赡,它和 staticFields 對應(yīng)的數(shù)據(jù)結(jié)構(gòu)是一樣的贫橙,我們直接分析,第一個(gè) fieldIdx疲迂,值為0尤蒿,對應(yīng)的 DexField 的索引值為int HelloWorld.a土铺。第二個(gè) accessFlags媒峡,值為0,對應(yīng)的ACC_開頭的數(shù)據(jù)為空甘桑,就是什么也沒有跑杭。說明我們這個(gè)實(shí)例字段為:int HelloWorld.a德谅≌觯可以對應(yīng)我們的源碼看看,我們確實(shí)定義了一個(gè)a實(shí)例變量组砚。

再接著糟红,根據(jù) directMethodsSize盆偿,有3個(gè)直接方法陈肛,我們先看第一個(gè)句旱,它對應(yīng)的數(shù)據(jù)結(jié)構(gòu)是 DexMethod谈撒,首先 methodIdx 指向的是 DexMethodId 的索引啃匿,值為0溯乒,找到對應(yīng)的索引值為 void HelloWorld.()裆悄。然后 accessFlages 為......為......為....我的個(gè)天光稼!我以為就這樣能蒙混過關(guān)了艾君,沒想到還真碰到一個(gè)uleb128數(shù)據(jù)不是占用一個(gè)字節(jié)的冰垄,這個(gè) accessFlags 對應(yīng)的值占用了三個(gè)字節(jié),“88 80 04”伴奥,為什么?因?yàn)槭前凑?uleb128格式 的數(shù)據(jù)讀出來的(還是自己去查查吧感局,這個(gè)坑先不填了询微,其實(shí)這種數(shù)據(jù)也不麻煩,就是前面字節(jié)上的最高位指定了是否需要下一個(gè)字節(jié)上的內(nèi)容)藻雌】韬迹“88 80 04”對應(yīng)的ACC_開頭的數(shù)據(jù)為 ACC_STATIC ACC_CONSTRUCTOR做个,表明這個(gè)方法是靜態(tài)的居暖,并且是構(gòu)造方法太闺。

最后跟束,看看 codeOff冀宴,它對應(yīng)了 DexCode 結(jié)構(gòu)的偏移略贮,DexCode 中存放了方法的指令集等信息逃延,也就是真正的代碼了揽祥。我們暫且不分析DexCode,就先看看它的偏移位置為“E0 03”拄丰,這個(gè)等于多少呢府树?uleb128轉(zhuǎn)化為16進(jìn)制數(shù)結(jié)果為:1E0h。也就是 DexCode 存放在偏移位置1E0h的位置上料按。

具體的 DexCode 我們就先不分析了奄侠,因?yàn)樗锩娲娣诺囊恍┲噶罹中枰鶕?jù)相關(guān)資料一一查找,有興趣的自己可以找資料看看载矿。剩下的兩個(gè)直接方法我們也不分析了。

接下來闷盔,我們看根據(jù) virtualMethodsSize弯洗,有1個(gè)虛方法,我們直接看馁筐。首先 methodIdx 的值為2涂召,對應(yīng)的 DexMethodId 的索引值為 int HelloWorld.getNumber(int, int)。然后accessFlags 為1敏沉,對應(yīng)的值為 ACC_PUBLIC果正,表明這是一個(gè) public 類。codeOff 為“FC 04”盟迟,對應(yīng)的位置為27Ch秋泳,這里就不上圖了,自己找找吧攒菠。

此篇文章由來:?

?部分來源于郭霖的微信公眾號Tryking的投稿迫皱。由操作和練習(xí)一遍有感而寫。作為學(xué)習(xí)記錄于此辖众。


Tryking 的博客地址:

參考自http://www.cnblogs.com/dacainiao/p/6035274.html

http://mp.weixin.qq.com/s/UgamIOqKd7McXUd1DosZcQ

http://blog.csdn.net/jiangwei0910410003/article/details/50668549

感謝以上作者卓起。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市凹炸,隨后出現(xiàn)的幾起案子戏阅,更是在濱河造成了極大的恐慌,老刑警劉巖啤它,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件奕筐,死亡現(xiàn)場離奇詭異舱痘,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)离赫,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進(jìn)店門芭逝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人渊胸,你說我怎么就攤上這事旬盯。” “怎么了翎猛?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵瓢捉,是天一觀的道長。 經(jīng)常有香客問我办成,道長,這世上最難降的妖魔是什么搂漠? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任迂卢,我火速辦了婚禮,結(jié)果婚禮上桐汤,老公的妹妹穿的比我還像新娘而克。我一直安慰自己,他們只是感情好怔毛,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布员萍。 她就那樣靜靜地躺著,像睡著了一般拣度。 火紅的嫁衣襯著肌膚如雪碎绎。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天抗果,我揣著相機(jī)與錄音筋帖,去河邊找鬼。 笑死冤馏,一個(gè)胖子當(dāng)著我的面吹牛日麸,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播逮光,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼代箭,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了涕刚?” 一聲冷哼從身側(cè)響起嗡综,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎副女,沒想到半個(gè)月后蛤高,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蚣旱,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年戴陡,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了塞绿。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,102評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡恤批,死狀恐怖异吻,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情喜庞,我是刑警寧澤诀浪,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站延都,受9級特大地震影響雷猪,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜晰房,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一求摇、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧殊者,春花似錦与境、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至海蔽,卻和暖如春共屈,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背党窜。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工趁俊, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人刑然。 一個(gè)月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓寺擂,卻偏偏與公主長得像,于是被迫代替她去往敵國和親泼掠。 傳聞我的和親對象是個(gè)殘疾皇子怔软,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評論 2 355

推薦閱讀更多精彩內(nèi)容