日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

深入理解Java Class文件格式(一)

 看風(fēng)景D人 2016-10-07

Class文件在Java體系結(jié)構(gòu)中的位置和作用


在上一篇博客中, 大致講解了Java虛擬機(jī)的體系結(jié)構(gòu)和執(zhí)行原理。 本篇博客主要講解能夠被JVM識(shí)別, 加載并執(zhí)行的class文件的格式。


對于理解JVM和深入理解Java語言, 學(xué)習(xí)并了解class文件的格式都是必須要掌握的功課。 原因很簡單, JVM不會(huì)理解我們寫的Java源文件, 我們必須把Java源文件編譯成class文件, 才能被JVM識(shí)別, 對于JVM而言, class文件相當(dāng)于一個(gè)接口, 理解了這個(gè)接口, 能幫助我們更好的理解JVM的行為;另一方面, class文件以另一種方式重新描述了我們在源文件中要表達(dá)的意思, 理解class文件如何重新描述我們編寫的源文件, 對于深入理解Java語言和語法都是很有幫助的。 另外, 不管是什么語言, 只要能編譯成class文件, 都能被JVM識(shí)別并執(zhí)行, 所以class文件不僅是跨平臺(tái)的基礎(chǔ), 也是JVM跨語言的基礎(chǔ), 理解了class文件格式, 對于我們學(xué)習(xí)基于JVM的其他語言會(huì)有很大幫助。 


總之, 在整個(gè)Java技術(shù)體系結(jié)構(gòu)中, class文件處于中間的位置, 對于理解整個(gè)體系有著承上啟下的作用。 如圖所示:



Class文件格式概述


class文件是一種8位字節(jié)的二進(jìn)制流文件, 各個(gè)數(shù)據(jù)項(xiàng)按順序緊密的從前向后排列, 相鄰的項(xiàng)之間沒有間隙, 這樣可以使得class文件非常緊湊, 體積輕巧, 可以被JVM快速的加載至內(nèi)存, 并且占據(jù)較少的內(nèi)存空間。 我們的Java源文件, 在被編譯之后, 每個(gè)類(或者接口)都單獨(dú)占據(jù)一個(gè)class文件, 并且類中的所有信息都會(huì)在class文件中有相應(yīng)的描述, 由于class文件很靈活, 它甚至比Java源文件有著更強(qiáng)的描述能力。

class文件中的信息是一項(xiàng)一項(xiàng)排列的, 每項(xiàng)數(shù)據(jù)都有它的固定長度, 有的占一個(gè)字節(jié), 有的占兩個(gè)字節(jié), 還有的占四個(gè)字節(jié)或8個(gè)字節(jié), 數(shù)據(jù)項(xiàng)的不同長度分別用u1, u2, u4, u8表示, 分別表示一種數(shù)據(jù)項(xiàng)在class文件中占據(jù)一個(gè)字節(jié), 兩個(gè)字節(jié), 4個(gè)字節(jié)和8個(gè)字節(jié)。 可以把u1, u2, u3, u4看做class文件數(shù)據(jù)項(xiàng)的“類型” 。

class文件中存在以下數(shù)據(jù)項(xiàng)(該圖表參考自《深入Java虛擬機(jī)》):

類型 名稱 數(shù)量
u4 magic 1
u2 minor_version 1
u2 major_version 1
u2 constant_pool_count 1
cp_info constant_pool constant_pool_count - 1
u2 access_flags 1
u2 this_class 1
u2 super_class 1
u2 interfaces_count 1
u2 interfaces interfaces_count
u2 fields_count 1
field_info fields fields_count
u2 methods_count 1
method_info methods methods_count
u2 attribute_count 1
attribute_info attributes attributes_count


下面對class文件中的每一項(xiàng)進(jìn)行詳細(xì)的解釋。


class文件中的魔數(shù)和版本號


(1) magic

在class文件開頭的四個(gè)字節(jié), 存放著class文件的魔數(shù), 這個(gè)魔數(shù)是class文件的標(biāo)志,他是一個(gè)固定的值: 0XCAFEBABE 。 也就是說他是判斷一個(gè)文件是不是class格式的文件的標(biāo)準(zhǔn), 如果開頭四個(gè)字節(jié)不是0XCAFEBABE, 那么就說明它不是class文件, 不能被JVM識(shí)別。


(2)minor_version 和 major_version

緊接著魔數(shù)的四個(gè)字節(jié)是class文件的此版本號和主版本號。 隨著Java的發(fā)展, class文件的格式也會(huì)做相應(yīng)的變動(dòng)。 版本號標(biāo)志著class文件在什么時(shí)候, 加入或改變了哪些特性。 舉例來說, 不同版本的javac編譯器編譯的class文件, 版本號可能不同, 而不同版本的JVM能識(shí)別的class文件的版本號也可能不同, 一般情況下, 高版本的JVM能識(shí)別低版本的javac編譯器編譯的class文件, 而低版本的JVM不能識(shí)別高版本的javac編譯器編譯的class文件。 如果使用低版本的JVM執(zhí)行高版本的class文件, JVM會(huì)拋出java.lang.UnsupportedClassVersionError 。具體的版本號變遷這里不再討論, 需要的讀者自行查閱資料。 


class文件中的常量池概述


在class文件中, 位于版本號后面的就是常量池相關(guān)的數(shù)據(jù)項(xiàng)。 常量池是class文件中的一項(xiàng)非常重要的數(shù)據(jù)。 常量池中存放了文字字符串, 常量值, 當(dāng)前類的類名, 字段名, 方法名, 各個(gè)字段和方法的描述符, 對當(dāng)前類的字段和方法的引用信息, 當(dāng)前類中對其他類的引用信息等等。 常量池中幾乎包含類中的所有信息的描述, class文件中的很多其他部分都是對常量池中的數(shù)據(jù)項(xiàng)的引用,比如后面要講到的this_class, super_class, field_info, attribute_info等, 另外字節(jié)碼指令中也存在對常量池的引用, 這個(gè)對常量池的引用當(dāng)做字節(jié)碼指令的一個(gè)操作數(shù)。  此外, 常量池中各個(gè)項(xiàng)也會(huì)相互引用。


class文件中的項(xiàng)constant_pool_count的值為1, 說明每個(gè)類都只有一個(gè)常量池。 常量池中的數(shù)據(jù)也是一項(xiàng)一項(xiàng)的, 沒有間隙的依次排放。常量池中各個(gè)數(shù)據(jù)項(xiàng)通過索引來訪問, 有點(diǎn)類似與數(shù)組, 只不過常量池中的第一項(xiàng)的索引為1, 而不為0, 如果class文件中的其他地方引用了索引為0的常量池項(xiàng), 就說明它不引用任何常量池項(xiàng)。class文件中的每一種數(shù)據(jù)項(xiàng)都有自己的類型, 相同的道理,常量池中的每一種數(shù)據(jù)項(xiàng)也有自己的類型。 常量池中的數(shù)據(jù)項(xiàng)的類型如下表:

常量池中數(shù)據(jù)項(xiàng)類型 類型標(biāo)志 類型描述
CONSTANT_Utf8 1 UTF-8編碼的Unicode字符串
CONSTANT_Integer 3 int類型字面值
CONSTANT_Float 4 float類型字面值
CONSTANT_Long 5 long類型字面值
CONSTANT_Double 6 double類型字面值
CONSTANT_Class 7 對一個(gè)類或接口的符號引用
CONSTANT_String 8 String類型字面值
CONSTANT_Fieldref 9 對一個(gè)字段的符號引用
CONSTANT_Methodref 10 對一個(gè)類中聲明的方法的符號引用
CONSTANT_InterfaceMethodref 11 對一個(gè)接口中聲明的方法的符號引用
CONSTANT_NameAndType 12 對一個(gè)字段或方法的部分符號引用


每個(gè)數(shù)據(jù)項(xiàng)叫做一個(gè)XXX_info項(xiàng), 比如, 一個(gè)常量池中一個(gè)CONSTANT_Utf8類型的項(xiàng), 就是一個(gè)CONSTANT_Utf8_info 。除此之外, 每個(gè)info項(xiàng)中都有一個(gè)標(biāo)志值(tag), 這個(gè)標(biāo)志值表明了這個(gè)常量池中的info項(xiàng)的類型是什么, 從上面的表格中可以看出, 一個(gè)CONSTANT_Utf8_info中的tag值為1, 而一個(gè)CONSTANT_Fieldref_info中的tag值為9 。

Java程序是動(dòng)態(tài)鏈接的, 在動(dòng)態(tài)鏈接的實(shí)現(xiàn)中, 常量池扮演者舉足輕重的角色。 除了存放一些字面量之外, 常量池中還存放著以下幾種符號引用:

(1) 類和接口的全限定名

(2) 字段的名稱和描述符

(3) 方法的名稱和描述符

在詳細(xì)講解常量池中的各個(gè)數(shù)據(jù)項(xiàng)之前, 我們有必要先了解一下class文件中的特殊字符串, 因?yàn)樵诔A砍刂校?特殊字符串大量的出現(xiàn),這些特殊字符串就是上面說的全限定名和描述符。 要理解常量池中的各個(gè)數(shù)據(jù)項(xiàng), 必須先了解這些特殊字符串。


對于class文件的講解會(huì)在后續(xù)博文中繼續(xù), 歡迎關(guān)注。



更多關(guān)于深入理解Java的文章, 請關(guān)注我的專欄 : http://blog.csdn.net/column/details/zhangjg-java-blog.html

更多關(guān)于Java和Android等其他技術(shù)的文章, 請關(guān)注我的博客: http://blog.csdn.net/zhangjg_blog



    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多