最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

類文件結(jié)構(gòu)

2023-04-25 08:08 作者:廢品批發(fā)  | 我要投稿

1.1 魔數(shù)與class文件的版本

class文件的前4個字節(jié)表示文件類型(16進制無符號數(shù)0XCAFEBABE, 1個16進制需要二進制4位表示, 8個16進制數(shù), 需要32位2進制數(shù)正好4個字節(jié)).

緊隨魔數(shù)之后的4個字節(jié)表示class文件的版本號.

使用vim查看class文件, 使用?:%!xxd?命令查看16進制, 結(jié)果如下圖:

class文件使用vim以16進制顯示

1.2 常量池

class文件的格式包含: 無符號數(shù)和表.??

無符號數(shù)容易理解, 可以表示數(shù)字、索引引用、數(shù)量值或者按照UTF8編碼構(gòu)成字符串.

表由多個無符號數(shù)或者其他表作為數(shù)據(jù)項組成的復(fù)合數(shù)據(jù)結(jié)構(gòu), 習(xí)慣性以?_info?結(jié)尾.?

表用于描述有層次關(guān)系的復(fù)合結(jié)構(gòu)的數(shù)據(jù), 整個class文件本質(zhì)上就是一張表.


常量池是class文件的第一個表, 文件版本號的后面就是常量池, 前兩個字節(jié)表示常量池的容量, 如上圖的:0X0050, 表示十進制80, 其實只有79個常量, 因為第0號位需要空出來, 當(dāng)后面數(shù)據(jù)要表示“不引用任何一個常量池項目”時, 可以把索引值置為0來實現(xiàn).


將class文件進行javap反編譯后, 可以看到常量池中確實只有79個.

javap命令反向編譯class文件

如果要了解class文件的javap命令的翻譯邏輯, 就需要先了解如下這個類型列表:

邏輯如下:

0x0050這是常量池的項目數(shù)量,0x0a是十進制10, 通過上面的表可知tag=10的是CONSTANT_Methodref_info, 然后這個表的下一部分是u2, u2表示兩個字節(jié), 用來表示這個方法所屬的類, 對應(yīng)的十六進制數(shù)是0x0011, 即17, 然后CONSTANT_Methodref_info這個表的最后一部分是一個u2, 使用同樣的方式在class的圖中找, 可以得到0x002d, 即45, 至此, javap中#1的Methodref的#17.#45就是這么來的, 以此類推即可得到j(luò)avap的整個反編譯內(nèi)容.

題外話:

CONSTANT_Utf8_info最大長度是2個字節(jié)表示, 2^16=65536, 這解釋了為什么變量名稱和方法名稱等不能超過64KB.

1.3 訪問標志

常量池之后的兩個字節(jié)就是訪問標志access_flags, 標識類或者接口層次的訪問信息, 包括:這個class是類還是接口; 是否是pulbic; 是否是abstract; 是否final;


訪問標志的取值從下表中的值求和得到:

常量池結(jié)束后的部分可通過上表查詢含義


1.4 類索引、父類索引與接口索引集合


class文件中一定會包含: 這個class的類的全名、父類的全名、實現(xiàn)的接口, class中依次排列這三種信息.

其中實現(xiàn)的接口是集合的形式, 集合種元素的順序就是源碼中 implements 后面接口的順序.

類索引、父類索引都是u2類型, 指向常量池中的對應(yīng)項.

接口索引集合首先是2個字節(jié)表示的集合元素數(shù)量, 如果為元素數(shù)量為0, 則沒有集合內(nèi)容部分;如果元素數(shù)量不為0, 其中的元素長度都是兩個字節(jié)的常量池索引值.


0021是訪問修飾,?請注意之后的部分

下圖是截取的另一個類:

黃色就是類,?父類,?接口信息

1.5 字段表集合

類的字段指的是類變量和實例變量, 不包含局部變量.

在上述的接口索引集合之后, 使用u2表示字段數(shù)量, 然后開始逐一列舉字段.

字段表的每一個字段結(jié)構(gòu)如下:

上圖中的attribute_info就是屬性表, 將在下文介紹.

class文件16進制
javap反編譯

綜上可見, 0x00020002000e000f的含義就是?private String a;? 這樣一句代碼.

關(guān)于簡單名稱、描述符、 全限定名:

全限定名與類的全名很像, 就是把" .?"?換成?"?/?"?, 通常一個全限定名結(jié)束后會以 "?; "?結(jié)尾, 以防止多個全限定名之間產(chǎn)生混淆.

簡單名稱: 方法ins(), 簡單名稱就是ins, 不要返回值和參數(shù), 也不要括號. 字段a的簡單名稱就是a.

描述符: java.lang.String的toString方法, 描述符:"?()Ljava/lang/String; ", 除了方法名看不出來, 其他都會顯示在其中, 方法參數(shù)列表在前, 返回值在后, 返回值先用標識符L表示是什么類型, 在跟上類的全限定名.

方法 int a(int x,Integer y, String[] z), 描述符是:"?(ILjava/lang/Integer;[Ljava/lang/String;)I ", 可見, 數(shù)組類型會在數(shù)組元素描述之前加一個"?[ ". 而對于字段的描述符就是描述字段的類型, 例如private String a; 描述符是:"?Ljava/lang/String; "

描述符含義對照表

字段表中不會列出超類或上層接口中繼承的字段, 但內(nèi)部類中可能會出現(xiàn)外部類的字段, 已實現(xiàn)對外部類的訪問性.

1.6 方法表集合


方法表與字段表使用的策略十分相似, 只是access_flags的可選項有所不同.

方法表的前面一定會有一個u2, 表示表的元素數(shù)量, 之后依次列舉元素.

至于方法中的代碼, 則被存儲于方法表的屬性表中, 屬性表的“code”這一項中將包含該信息, 屬性表就是上圖中attribute_info, 字段表中的字段也可能具備該結(jié)構(gòu), 需要看這個字段是否是有附加信息(如static final修飾的字段).

1.7 屬性表集合

屬性表在class文件、字段表、方法表中都有.

屬性表中的項沒有順序要求, 可以自定義添加新的項, 虛擬機會自動忽略不認識的項.

上圖中的17個code部分, 每一個字節(jié)都是一個字節(jié)碼指令. 例如第一個字節(jié)碼0x2a, 就表示aload.

從javap的顯示可以看到構(gòu)造方法args_size=1, 但是源碼中并沒有發(fā)現(xiàn)有參數(shù), 這個參數(shù)就是this. 如果是靜態(tài)方法就不會有這個arg了.

從javap的方法表的LocalVariableTable可見局部變量表的slot: 0 就是this, start: 0, length: 17, 表示這個變量的生命周期從code:0 到 code:16.


泛型中參數(shù)化類型(用來記錄對象原本類型的信息)存儲于Signature,LocalVariableTypeTable是泛型的特征簽名.



類文件結(jié)構(gòu)的評論 (共 條)

分享到微博請遵守國家法律
衡水市| 仁化县| 祁门县| 哈尔滨市| 城口县| 岳阳市| 抚顺县| 读书| 承德市| 龙口市| 会宁县| 临清市| 桓仁| 禄丰县| 民乐县| 邓州市| 葵青区| 黄浦区| 神农架林区| 肥乡县| 岳普湖县| 嵊州市| 石屏县| 金乡县| 迁安市| 长兴县| 梨树县| 全南县| 内乡县| 玉屏| 石渠县| 周口市| 嫩江县| 新绛县| 和田县| 十堰市| 礼泉县| 梨树县| 麦盖提县| 鸡泽县| 涿州市|