JVM學(xué)習(xí)筆記(4)-JVM類文件結(jié)構(gòu)

簡(jiǎn)介

Class文件是Java虛擬機(jī)執(zhí)行引擎的數(shù)據(jù)入口琐驴,也是Java技術(shù)體系的基礎(chǔ)構(gòu)成之一绝淡。了解Class文件的結(jié)構(gòu)對(duì)后面進(jìn)一步了解虛擬機(jī)執(zhí)行引擎很有重要的意義牢酵。

我們的知道,Java是跨平臺(tái)的語言馍乙。在Java發(fā)展之初,設(shè)計(jì)者們就考慮過了在Java虛擬機(jī)上運(yùn)行其它語言的可能性撑瞧。時(shí)至今日商業(yè)機(jī)構(gòu)和開源機(jī)構(gòu)以及在Java語言之外發(fā)展出一大批在Java虛擬機(jī)上運(yùn)行的語言显蝌,如Clojure,Groovy,JRuby,Jython,Scala琅束,等等。實(shí)現(xiàn)語言無關(guān)性的基礎(chǔ)仍然是虛擬機(jī)和字節(jié)碼存儲(chǔ)格式料滥,使用Java編譯器可以把Java代碼編譯為存儲(chǔ)字節(jié)碼的Class文件葵腹,使用JRuby等其它語言的編譯器一樣可以把程序編譯成Class文件屿岂,虛擬機(jī)不需要關(guān)心Class來源于什么語言爷怀,只要它符合Class文件應(yīng)用的結(jié)構(gòu)就可以在Java虛擬機(jī)中運(yùn)行。

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

Class文件是一組以8字節(jié)為基礎(chǔ)單位的二進(jìn)制流烤惊,各個(gè)數(shù)據(jù)項(xiàng)目嚴(yán)格按照順序緊湊地排列在Class文件之中柒室,中間沒有添加任何分隔符逗宜,這使得整個(gè)Class文件中存儲(chǔ)的內(nèi)容幾乎全部是程序運(yùn)行的必要數(shù)據(jù)纺讲,沒有空隙存在。當(dāng)遇到需要占用8位字節(jié)以上空間的數(shù)據(jù)項(xiàng)時(shí)防楷,則會(huì)按照高位在前的方式分割成若干個(gè)8位字節(jié)進(jìn)行存儲(chǔ)复局。整個(gè)Class文件本質(zhì)上就是一張表。

占用大小 字段描述 數(shù)量
4bit magic:魔數(shù)峦剔,用于標(biāo)識(shí)文件類型角钩,對(duì)于java來說是0xCAFEBABE 1
2bit minor_version:次版本號(hào) 1
2bit major_version:主版本號(hào) 1
2bit constant_pool_count:常量池大小递礼,從1開始而不是0。當(dāng)這個(gè)值為0時(shí)辫愉,表示后面沒有常量 1
不定 constant_pool:#常量池 constant_pool_count-1
2bit access_flags:訪問標(biāo)志恭朗,標(biāo)識(shí)這個(gè)class是類還是接口依疼、public律罢、abstract、final 1
2bit this_class:類索引 1
2bit super_class:父類索引 1
2bit interfaces_count:接口計(jì)數(shù)器 1
每個(gè)2bit interfaces:接口索引集合 interfaces_count
2bit fields_count:字段的數(shù)量 1
不定 fields:#字段表 fields_count
2bit methods_count:方法數(shù)量 1
不定 methods:#方法表 methods_count
2bit attributes_count:屬性數(shù)量 1
不定 attrbutes:#屬性表 attributes_count

我們可以使用WinHex來查看class文件


class示例圖

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

每個(gè)Class文件頭4個(gè)字節(jié)稱為魔數(shù),它的唯一作用是確定這個(gè)文件是否是一個(gè)能被虛擬機(jī)接受的Class文件稀余。
根據(jù)class示例圖可以看出魔數(shù)值(4個(gè)字節(jié))為0xCAFEBABE睛琳;緊接著第5和第6個(gè)字節(jié)是次版本號(hào)师骗,第7讨惩、8個(gè)字節(jié)是主版本號(hào)荐捻。這里需要注意高版本的JDK能向下兼容以前版本的Class文件寡夹,但不能運(yùn)行以后版本的Class文件菩掏。

常量池

常量池可以理解為Class文件之中的資源倉庫智绸。常量池中主要存放兩大類常量:字面量和符號(hào)引用访忿。字面量比較接近于Java語言層面的常量概念,如文本字符串迹恐、聲明為final的常量值等游添。而符號(hào)引用則屬于編譯原理方面的概念,包括了下面三類常量:

  • 類和接口的全限定名
  • 字段的名稱和描述符
  • 方法的名稱和描述符

Java代碼在進(jìn)行Javac編譯的時(shí)候找都,并不像C和C++那樣有“連接”這一步驟能耻,而是在虛擬機(jī)加載Class文件的時(shí)候進(jìn)行動(dòng)態(tài)連接亡驰。也就是說凡辱,在Class文件中不會(huì)保存各個(gè)方法、字段的最終內(nèi)存布局信息洪燥,因此這些字段捧韵、方法的符合引用不經(jīng)過運(yùn)行期轉(zhuǎn)換的話無法得到真正的內(nèi)存入口地址汉操,也就無法直接被虛擬機(jī)使用。當(dāng)虛擬機(jī)運(yùn)行時(shí)芒篷,需要從常量池獲得對(duì)應(yīng)的符號(hào)引用、再在類創(chuàng)建時(shí)或運(yùn)行時(shí)解析梭伐、翻譯到具體的內(nèi)存地址之中

訪問標(biāo)志

在常量池結(jié)束之后糊识,緊接著的兩個(gè)字節(jié)代表訪問標(biāo)志(access_flags),這個(gè)標(biāo)志用于識(shí)別一些類或者接口層次的訪問信息愉耙,包括:這個(gè)Class是類還是接口:是否定義為public類型拌滋;是否定義為abstract類型;如果是類的話赌渣,是否被生命為final等

類索引坚芜、父類索引與接口索引集合

類索引和分類索引都是一個(gè)u2類型的數(shù)據(jù),而接口索引集合是一組u2類型的數(shù)據(jù)集合鸿竖,Class文件中由三項(xiàng)數(shù)據(jù)來確定這個(gè)類的繼承關(guān)系缚忧。類索引用于確定這個(gè)類的全限定名杈笔,父類索引用于確定這個(gè)類的父類的全限定名蒙具。對(duì)于接口索引集合,入口的第一項(xiàng)u2類型的數(shù)據(jù)為接口計(jì)數(shù)器店量,表示索引表的容量融师。

字段表集合

字段表用于描述接口或者類中聲明的變量旱爆。字段(field)包括類級(jí)變量以及實(shí)例級(jí)變量,但不包括在方法內(nèi)部聲明的局部變量怀伦。字段表中字段的各種描述信息(作用域比如public房待,private,是否被final拜鹤,static修飾流椒,是否可序列化等)均使用標(biāo)志位表示,名稱則引用常量池中的常量來描述惯裕。

方法表集合

在方法表中蜻势,方法的描述和字段的描述基本一致域那,依次包括訪問標(biāo)志(access_flags)、名稱索引(name_index)败许、描述符索引(descriptor_index)市殷、屬性表集合(attributes)幾項(xiàng)刹衫。
方法中的代碼經(jīng)過編譯器編譯成字節(jié)碼指令后存放在方法屬性表集合中一個(gè)名為“Code”的屬性里面带迟。
如果父類方法在子類中沒有被重寫,方法表集合中就不會(huì)出現(xiàn)來自父類的方法信息嗅绰。

屬性表集合

Class文件、字段表翠语、方法表都可以攜帶自己的屬性表集合财边,以用于描述某些場(chǎng)景專有的信息酣难。為了能正確解析Class文件,在Java SE 7中預(yù)定義了21項(xiàng)屬性鲸鹦,虛擬機(jī)在運(yùn)行時(shí)會(huì)忽略他不認(rèn)識(shí)的屬性。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末齐板,一起剝皮案震驚了整個(gè)濱河市甘磨,隨后出現(xiàn)的幾起案子济舆,更是在濱河造成了極大的恐慌莺债,老刑警劉巖齐邦,帶你破解...
    沈念sama閱讀 221,576評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異我纪,居然都是意外死亡浅悉,警方通過查閱死者的電腦和手機(jī)券犁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門苛坚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事枷莉。” “怎么了冒掌?”我有些...
    開封第一講書人閱讀 168,017評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)召衔。 經(jīng)常有香客問我苍凛,道長(zhǎng),這世上最難降的妖魔是什么宣肚? 我笑而不...
    開封第一講書人閱讀 59,626評(píng)論 1 296
  • 正文 為了忘掉前任霉涨,我火速辦了婚禮惭适,結(jié)果婚禮上腥沽,老公的妹妹穿的比我還像新娘。我一直安慰自己今阳,他們只是感情好盾舌,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,625評(píng)論 6 397
  • 文/花漫 我一把揭開白布窿锉。 她就那樣靜靜地躺著,像睡著了一般窑多。 火紅的嫁衣襯著肌膚如雪洼滚。 梳的紋絲不亂的頭發(fā)上遥巴,一...
    開封第一講書人閱讀 52,255評(píng)論 1 308
  • 那天铲掐,我揣著相機(jī)與錄音,去河邊找鬼豪椿。 笑死斯入,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的增蹭。 我是一名探鬼主播磅摹,決...
    沈念sama閱讀 40,825評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼滋迈,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了户誓?” 一聲冷哼從身側(cè)響起饼灿,我...
    開封第一講書人閱讀 39,729評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎帝美,沒想到半個(gè)月后碍彭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,271評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡悼潭,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,363評(píng)論 3 340
  • 正文 我和宋清朗相戀三年庇忌,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片舰褪。...
    茶點(diǎn)故事閱讀 40,498評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡皆疹,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出捎迫,到底是詐尸還是另有隱情,我是刑警寧澤颗祝,帶...
    沈念sama閱讀 36,183評(píng)論 5 350
  • 正文 年R本政府宣布折汞,位于F島的核電站翩腐,受9級(jí)特大地震影響何什,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜罐栈,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,867評(píng)論 3 333
  • 文/蒙蒙 一柑贞、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧摄欲,春花似錦、人聲如沸迟隅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至嘀倒,卻和暖如春括儒,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工洽故, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留哈踱,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,906評(píng)論 3 376
  • 正文 我出身青樓质欲,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,507評(píng)論 2 359

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