Class類文件結構分析

Class文件中存儲著Java虛擬機指令集和符號表以及若干輔助信息。它使用的是一種平臺無關的字節(jié)碼儲存格式,不同的虛擬機實現(xiàn)都可以載入執(zhí)行這種平臺無關的字節(jié)碼桐猬。Java虛擬機不與任何語言綁定插龄,只與Class文件這種特定二進制文件格式關聯(lián),原則上任何語言都可以編譯成Class文件在Java虛擬機上運行招盲。

一、 Class類文件結構


Class文件格式采用一種類似C語言結構體的偽結構來存儲數(shù)據(jù)嘉冒,這種偽結構中只有兩種數(shù)據(jù)類型:無符號數(shù)和表曹货。

1.1 無符號數(shù)

無符號數(shù)屬于基本數(shù)據(jù)類型咆繁,以u1,u2顶籽,u4玩般,u8來分別代表1個字節(jié)、2個字節(jié)礼饱、4個字節(jié)和8個字節(jié)的無符號數(shù)壤短,無符號數(shù)可以用來描述數(shù)字、索引引用慨仿、數(shù)量值或者按照UTF-8編碼構成字符串值久脯。

1.2 表

表是由多個無符號數(shù)或者其他表作為數(shù)據(jù)項構成的復合數(shù)據(jù)類型。表用于描述有層次關系的復合結構的數(shù)據(jù)镰吆,整個Class文件本質(zhì)上就是一張表帘撰。Class中以_info結尾代表一張表。

二万皿、Class字節(jié)碼解析


Class文件是一組以8位字節(jié)為基礎單位的二進制流摧找,各個數(shù)據(jù)項目嚴格的按照順序緊湊的排列在Class文件中。當遇到占用8字節(jié)以上空間的數(shù)據(jù)項時牢硅,則會按照高位在前的方式分割成若干個8位字節(jié)進行存儲蹬耘。Class內(nèi)部不包含任何分隔符,數(shù)據(jù)存儲順序數(shù)量都被嚴格限定减余,不允許任何改動综苔。下面看看具體數(shù)據(jù)項的含義:

2.1 魔數(shù)(Magic Number)

每個Class文件的頭4個字節(jié)稱為魔數(shù)(Magic Number),它唯一作用就是用來確定文件是否能被虛擬機接受位岔。

很多文件存儲標準中都用魔數(shù)進行身份標識如筛,如圖片gif,jpeg都在文件頭部中存儲著魔數(shù)抒抬。使用魔數(shù)而不是用擴展名來進行識別主要是基于安全考慮杨刨,因為擴展名可以被隨意改動。

2.2 版本號

接下來的4個字節(jié)存儲著Class文件的版本號擦剑,第五第六個字節(jié)為次版本號(Minor Version)妖胀,第七第八為主版本號(Major Version)。版本號主要用于版本控制惠勒,高版本的JDK能向下兼容以前版本的Class文件赚抡,但不能運行以后版本的Class文件。

2.3 常量池入口

緊接著版本號之后的就是常量池入口捉撮,常量池入口后面還必須有一個u2數(shù)據(jù)項作為常量池容量計數(shù)器(因為常量池數(shù)量不固定)怕品。

常量池是一個表類型的數(shù)據(jù)項妇垢,相當于Class文件的資源倉庫巾遭,與Class文件其他項目關聯(lián)最多肉康,占用Class空間最大的數(shù)據(jù)項之一,且是第一個出現(xiàn)的表類型數(shù)據(jù)項目灼舍。

常量池主要存儲兩大類常量:字面量(Literal)和符號引用(Symbolic References)

字面量相當于Java語言中的常量概念吼和,比如字符串,聲明為final的常量值骑素。
符號引用則屬于編譯原理方面的概念包括三類常量:

  • 類和接口的全限定名(Fully Qualified Name)
  • 字段的名稱和描述符(Descriptor)
  • 方法的名稱和描述符

Class文件不會保存各個方法字段的最終內(nèi)存布局信息炫乓,因為這些字段、方法和符號引用不經(jīng)過運行期轉換(動態(tài)連接)的話無法得到真正內(nèi)存入口地址献丑,也就無法被虛擬機使用末捣。當虛擬機運行時,需要從常量池獲得對應的符號引用创橄,再在類創(chuàng)建或運行時解析翻譯到具體的內(nèi)存地址之中箩做。

常量池中的每一項常量都是一個表(JDK1.7中有14種)。包括UTF-8編碼的字符串表妥畏,整型字面量表邦邦,浮點型字面量表,長整型字面常量表醉蚁,類和接口的符號引用表燃辖,字段符號引用表,類中的方法符號引用表网棍,接口中方法符號引用表等等黔龟。這些表都會有各自不同的結構。

2.4 訪問標志

常量池之后就是由兩個字節(jié)代表的訪問標識(access flags)這些標識用于識別一些類或者接口層次的訪問信息滥玷,包括這個Class是類還是接口捌锭;是否定義為public;是否定義為abstract類型罗捎;是否被final修飾观谦。

2.5 類索引、父類索引桨菜、接口索引

訪問標志位之后就是u2類型的類索引豁状,父類索引和接口索引集合。Class文件由這三項數(shù)據(jù)確定這個類的繼承關系倒得。這三項數(shù)據(jù)(u2類型的索引值)各指向類型為CONSTANT_Class_info的類描述符常量泻红。

2.6 字段表集合

字段表用于描述接口或者類中聲明的變量。字段(field)包括類級變量以及實例級變量霞掺,但不包括在方法內(nèi)部聲明的局部變量谊路。字段表中字段的各種描述信息(作用域比如public,private菩彬,是否被final缠劝,static修飾潮梯,是否可序列化等)均使用標志位表示,名稱則引用常量池中的常量來描述惨恭。

2.7 方法表集合

在方法表中秉馏,方法的描述和字段的描述基本一致,依次包括訪問標志(access_flags)脱羡、名稱索引(name_index)萝究、描述符索引(descriptor_index)、屬性表集合(attributes)幾項锉罐。

方法中的代碼經(jīng)過編譯器編譯成字節(jié)碼指令后存放在方法屬性表集合中一個名為“Code”的屬性里面帆竹。

如果父類方法在子類中沒有被重寫,方法表集合中就不會出現(xiàn)來自父類的方法信息脓规。

2.8 屬性表集合

Class文件馆揉、字段表、方法表都可以攜帶自己的屬性表集合抖拦,以用于描述某些場景專有的信息升酣。

為了能正確解析Class文件,在Java SE 7中預定義了21項屬性态罪,虛擬機在運行時會忽略他不認識的屬性噩茄。

三、字節(jié)碼指令


Java虛擬機的指令是由一個字節(jié)長度的复颈、代表著某種特定操作含義的數(shù)字(操作碼绩聘,Opcode)以及跟隨其后的零個至多個代表此操作所需要的參數(shù)(操作數(shù),Operands)構成耗啦。

常用指令:

  • 加載存儲指令凿菩,將數(shù)據(jù)在棧幀中的局部變量表和操作數(shù)棧之間來回傳輸
  • 運算指令,對兩個操作數(shù)棧上的值進行某種特定運算帜讲,并把結果重新寫入操作棧衅谷,包括加減乘除邏輯與或非
  • 類型轉換指令,將兩種不同的數(shù)值類型進行相互轉換似将,這些轉換一般用于實現(xiàn)用戶代碼中的顯式類型轉換操作获黔,或者用來處理字節(jié)碼指令集中數(shù)據(jù)類型相關指令代碼無法與數(shù)據(jù)類型一一對應的問題。另在验,類型轉換指令永遠不可能導致虛擬機運行異常玷氏。
  • 對象創(chuàng)建與訪問指令,創(chuàng)建對象數(shù)組訪問對象等
  • 操作數(shù)棧管理指令腋舌,Java虛擬機提供了一些用于直接操作操作數(shù)棧的指令盏触,包括入棧,出棧,棧頂端兩個數(shù)據(jù)交換
  • 控制轉移指令赞辩,可以讓Java虛擬機有條件或無條件地從指定的位置指令而不是控制轉移指令的下一條指令繼續(xù)執(zhí)行程序雌芽,包括條件分支ifxxx,復合條件分支诗宣,無條件分支goto等膘怕。
  • 方法調(diào)用和返回指令想诅,調(diào)用對象實例方法召庞,調(diào)用接口方法,調(diào)用類方法来破,運行時動態(tài)解析出調(diào)用點限定符所引用的方法篮灼,返回指令根據(jù)返回值類型區(qū)分
  • 異常處理指令,Java程序中顯式拋出異常的操作(throw)都是由athrow指令實現(xiàn)徘禁,異常處理不是字節(jié)碼指令實現(xiàn)诅诱,而是采用異常表實現(xiàn)
  • 同步指令,方法級同步和方法內(nèi)部一段指令序列的同步(通過管程Monitor支持)送朱,執(zhí)行線程要求先持有管程娘荡,然后才能執(zhí)行方法,當方法執(zhí)行完成后釋放管程驶沼;方法執(zhí)行期間炮沐,執(zhí)行線程持有管程,任何一個線程都無法再獲取同一個管程
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末回怜,一起剝皮案震驚了整個濱河市大年,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌玉雾,老刑警劉巖翔试,帶你破解...
    沈念sama閱讀 222,681評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異复旬,居然都是意外死亡垦缅,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評論 3 399
  • 文/潘曉璐 我一進店門驹碍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來失都,“玉大人,你說我怎么就攤上這事幸冻〈馀樱” “怎么了?”我有些...
    開封第一講書人閱讀 169,421評論 0 362
  • 文/不壞的土叔 我叫張陵洽损,是天一觀的道長庞溜。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么流码? 我笑而不...
    開封第一講書人閱讀 60,114評論 1 300
  • 正文 為了忘掉前任又官,我火速辦了婚禮,結果婚禮上漫试,老公的妹妹穿的比我還像新娘六敬。我一直安慰自己,他們只是感情好驾荣,可當我...
    茶點故事閱讀 69,116評論 6 398
  • 文/花漫 我一把揭開白布外构。 她就那樣靜靜地躺著,像睡著了一般播掷。 火紅的嫁衣襯著肌膚如雪审编。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,713評論 1 312
  • 那天歧匈,我揣著相機與錄音垒酬,去河邊找鬼。 笑死件炉,一個胖子當著我的面吹牛勘究,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播斟冕,決...
    沈念sama閱讀 41,170評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼口糕,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了宫静?” 一聲冷哼從身側響起谭网,我...
    開封第一講書人閱讀 40,116評論 0 277
  • 序言:老撾萬榮一對情侶失蹤摊鸡,失蹤者是張志新(化名)和其女友劉穎懦尝,沒想到半個月后蝇摸,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,651評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡捌袜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,714評論 3 342
  • 正文 我和宋清朗相戀三年说搅,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片虏等。...
    茶點故事閱讀 40,865評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡弄唧,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出霍衫,到底是詐尸還是另有隱情候引,我是刑警寧澤,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布敦跌,位于F島的核電站澄干,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜麸俘,卻給世界環(huán)境...
    茶點故事閱讀 42,211評論 3 336
  • 文/蒙蒙 一辩稽、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧从媚,春花似錦逞泄、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,699評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至拂檩,卻和暖如春侮腹,著一層夾襖步出監(jiān)牢的瞬間嘲碧,已是汗流浹背稻励。 一陣腳步聲響...
    開封第一講書人閱讀 33,814評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留愈涩,地道東北人望抽。 一個月前我還...
    沈念sama閱讀 49,299評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像履婉,于是被迫代替她去往敵國和親煤篙。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,870評論 2 361

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