深入理解java虛擬機(三)--類文件結(jié)構(gòu)

? ? Write Once Run Anywhere。各種不同平臺的虛擬機與所有平臺都統(tǒng)一使用的程序存儲格式---字節(jié)碼(ByteCode)是構(gòu)成平臺無關(guān)性的基石传惠。

? ? 語言無關(guān)性也越來越被開發(fā)者重視,實現(xiàn)語言無關(guān)性的基礎(chǔ)仍然是虛擬機和字節(jié)碼存儲格式南用。

一耗跛、Class類文件的結(jié)構(gòu)

? ? ? Class文件是一組以8位字節(jié)為基礎(chǔ)單位的二進制流口柳,各個數(shù)據(jù)項目嚴(yán)格按照順序緊湊地排列在Class文件之中缠俺,中間沒有添加任何分隔符显晶,這使得整個Class文件中存儲的內(nèi)容幾乎全部是程序運行的必要數(shù)據(jù),沒有空隙存在壹士。當(dāng)遇到需要占用8位字節(jié)以上的空間的數(shù)據(jù)項時磷雇,則會按照高位在前的方式分割成若干個0位字節(jié)進行存儲。Class文件中只有兩種數(shù)據(jù)類型:無符號數(shù)和表躏救。

? ? ? 無符號數(shù)屬于基本數(shù)據(jù)類型倦春,以u1,u2落剪,u4,u8來分別代表1個字節(jié)尿庐、2個字節(jié)忠怖、4個字節(jié)、8個字節(jié)的無符號數(shù)抄瑟,無符號數(shù)可以用來描述數(shù)字凡泣、索引引用、數(shù)量值或者按照UTF-8編碼構(gòu)成字符串皮假。

? ? ? 表是由多個無符號數(shù)或者其他表作為數(shù)據(jù)項構(gòu)成的符合數(shù)據(jù)類型鞋拟,所有表都習(xí)慣性地以“_info”結(jié)尾。表用于描述有層次關(guān)系的符合結(jié)構(gòu)的數(shù)據(jù)惹资,整個Class文件本質(zhì)上就是一張表贺纲。

? ? ? 表6-1

1、魔數(shù)與Class文件的版本

? ? ? 每個Class文件的頭4個字節(jié)稱為魔數(shù)(Magic Number)褪测,它的唯一作用是確定這個文件是否為一個虛擬機接受的Class文件猴誊。緊接著魔數(shù)的4個字節(jié)存儲的是Class文件的版本號:第5和第6個字節(jié)是次版本號(Minor Version),第7和第8個字節(jié)是主版本號(Major Version)侮措。Java 的版本號是從45開始的懈叹,高版本的JDK能向下兼容以前版本的Class文件,不能執(zhí)行超過其版本號的Class文件分扎。表中列出了從JDK1.1到JDK1.7澄成,主流JDK版本編譯器輸出的默認和可支持的Class文件版本號。

? ? 表6-2 class文件版本號

2、常量池

? ? ? 緊接著主次版本號之后的是常量池入口墨状,常量池可以理解為Class文件中的資源倉庫卫漫,它是Class文件結(jié)構(gòu)中與其他項目關(guān)聯(lián)最多的數(shù)據(jù)類型,也是占用Class文件空間最大的數(shù)據(jù)項目之一歉胶,同時它還是在Class文件中第一個出現(xiàn)的表類型數(shù)據(jù)項目汛兜。

? ? ? 由于常量池中常量的數(shù)量不是固定的,所以在常量池的入口需要放置一項u2類型的數(shù)據(jù)通今,代表常量池容量計數(shù)值(constant_pool_count)粥谬。這個容量計數(shù)是從1開始的。

? ? ? ? 常量池中主要存放兩大類常量:字面量(Literal)和符號引用(Symbolic References)辫塌。字面量比較接近于Java語言層面的常量概念漏策,如文本字符串,聲明為final的常量值等臼氨。而符號引用則屬于編譯原理方面的概念掺喻,包括了下面三類常量:類和接口的全限定名(Full Qualified Name)、字段的名稱和描述符(Descriptor)储矩、方法的名稱和描述符感耙。

? ? ? 常量池中每一項常量都是一個表,總共有14中標(biāo)持隧,都有一個共同的特點即硼,就是開始的第一位是一個u1類型的標(biāo)志位(tag),代表當(dāng)前這個常量屬于哪種常量類型屡拨。

? ? ? 表6-3 常量池的項目類型

? ? ? ? 之所以說常量池是最繁瑣的的數(shù)據(jù)只酥,是因為這14種常量類型各自均有自己的結(jié)構(gòu)。CONSTANT_Class_info類型的常量代表一個類或者接口的符號引用呀狼。表6-4


? ? ? ? tag是標(biāo)志位裂允,它用于區(qū)分常量類型;name_index是一個索引值哥艇,它指向常量池中一個CONSTANT_Uft8_info類型常量绝编,此常量代表了這個類(或者接口)的全限定名。表6-5


? ? ? ? ? length值說明了這個UTF-8編碼的字符串長度是多少字節(jié)貌踏,它后面緊跟著的長度為length字節(jié)的連續(xù)數(shù)據(jù)是一個使用UTF-8縮略編碼表示的字符串瓮增。由于Class文件中方法、字段等都需要引用CONSTANT_Uft8_info型常量來描述名稱哩俭,所以CONSTANT_Uft8_info型常量的最大長度也就是Java中方法绷跑、字段名的最大長度。而length最大值為65535.所以Java程序中不能定義超過64KB英文字符的變量或方法名凡资,否則將會無法編譯砸捏。表6-6



3谬运、訪問標(biāo)志

? ? ? 在常量池結(jié)束之后,緊接著的兩個字節(jié)代表訪問標(biāo)志(access_flags)垦藏,這個標(biāo)志用于識別一些類或者接口層次的訪問信息梆暖,包括:這個Class是類還是接口;是否定義為public類型掂骏;是否定義為abstract類型轰驳;如果是類的話,是否被聲明為final等弟灼。具體見下表级解。

? ? ? 表6-7 訪問標(biāo)志


? ? ? access_flag中一共有16個標(biāo)志位可以使用,當(dāng)前只定義了其中8個田绑,沒有使用到的標(biāo)志要求一律為0勤哗。

4、類索引掩驱、父類索引與接口索引集合

? ? 類索引(this_class)和父類索引(super_class)都是一個u2類型的數(shù)據(jù)芒划,而接口索引集合(interface)是一組u2類型的數(shù)據(jù)的集合,Class文件中由這三項數(shù)據(jù)來確定這個類的繼承關(guān)系欧穴。類索引用于確定這個類的全限定名民逼,父類索引用于確定這個類的父類的全限定名。

? ? 類索引涮帘、父類索引和接口索引集合都按順序排列在訪問標(biāo)志之后后拼苍,類索引和父類索引用兩個u2類型的索引值表示,他們各自指向一個類型為CONSTANT_Class_info的描述符常量焚辅,通過CONSTANT_Class_info類型的常量中的索引值可以找到定義在CONSTANT_Utf8_info類型的常量中的全限定名字符串。

? ? ? 對于接口索引集合苟鸯,入口的第一項----u2類型的數(shù)據(jù)為接口計數(shù)器(interfaces_count)同蜻,表示索引表的容量。如果該類沒有實現(xiàn)任何接口早处,則該計數(shù)器值為0湾蔓,后面接口的索引表不再占用任何字節(jié)。

5砌梆、字段表集合

? ? ? 字段表(field_info)用于描述接口或者類中聲明的變量默责。字段(field)包括類級變量以及實例級變量,但不包括在方法內(nèi)部聲明的局部變量咸包。

? ? ? 表6-8 字段表結(jié)構(gòu)

? ? ? 字段修飾符放在access_flags項目中桃序,它與類中的access_flags項目是非常類似的,都是一個u2的數(shù)據(jù)類型烂瘫。

? ? ? ? 表6-9 字段訪問標(biāo)志

? ? ? ? 在實際情況中媒熊,ACC_PUBLIC、ACC_PRIVATE 、ACC_PROTECTED三個標(biāo)志最多只能選擇其中一個芦鳍,ACC_FINAL 嚷往、ACC_VOLATILE不能同時選擇。接口之中的字段必須有ACC_PUBLIC 柠衅、ACC_STATIC皮仁、 ACC_STATIC、 ACC_FINAL標(biāo)志菲宴,這些是由Java語言規(guī)則決定的贷祈。

? ? ? ? 緊跟access_flags標(biāo)志的是兩項索引值:name_index和descriptor_index。它們都是對常量池的引用裙顽,分別代表著字段的簡單名稱以及字段和方法的描述符付燥。

? ? ? ? 字段和方法的描述符的作用是用來描述字段的數(shù)據(jù)類型、方法的參數(shù)列表(包括數(shù)量愈犹、類型以及順序)和返回值键科。根據(jù)描述符規(guī)則,基本數(shù)據(jù)類型(byte漩怎、char勋颖、double 、float勋锤、 int饭玲、 long、 short叁执、 boolean)以及代表無返回值的void類型都用一個大寫字母來表示茄厘,而對象類型則用字符L加對象的全限定名來表示。表6-10谈宛。

6次哈、方法表集合

? ? ? 方法表結(jié)構(gòu)如同字段表一樣,依次包括了訪問標(biāo)志(access_flag)吆录、名稱索引(name_index)窑滞、描述符索引(descriptor_index)、屬性表集合(attribute)幾項恢筝,這些數(shù)據(jù)項目的含義也類似哀卫,僅在訪問標(biāo)志和屬性表集合的可選項中有所區(qū)別。

? ? ? 表6-11 方法表結(jié)構(gòu)

? ? ? ? 因為volatile關(guān)鍵字和transient關(guān)鍵字不能修飾方法撬槽,所以方法表的訪問標(biāo)志中沒有了ACC_VOLATILE標(biāo)志和ACC_TRANSIENT標(biāo)志此改。與之相對的,synchronized侄柔、native带斑、strictfp和abstract關(guān)鍵字可以修飾方法鼓寺,所以方法表的訪問標(biāo)志中增加了ACC_SYNCHRONIXED 、ACC_NATIVE勋磕、 ACC_STRICTFP和ACC_ABSTRACT標(biāo)志妈候。對于方法表,所有標(biāo)志位及其取值見表6-12挂滓。

7苦银、屬性表集合

? ? ? 屬性表(attribute_info),在Class文件赶站、字段表吸祟、方法表都可以攜帶自己的屬性表集合焰枢,用于描述某些場景專有的信息。表6-13



對于每個屬性,它的名稱需要從常量池中引用一個CONSTANT_Utf8_info類型的常量來表示碰镜,而屬性值的結(jié)構(gòu)則是完全自由定義的褪子,只需要通過一個u4的長度屬性去說明屬性值所占用的位數(shù)即可百揭。

? 表6-14 屬性表結(jié)構(gòu)

? Code屬性

? ? Java程序方法體中的代碼經(jīng)過Javac編譯器處理后塞俱,最終變?yōu)樽止?jié)碼指令存儲在COde屬性內(nèi)。Code屬性出現(xiàn)在方法表的屬性集合中渣窜,但并非所有方法表都必須存在這個屬性铺根,譬如接口或者抽象類中的方法就不存在Code屬性,如果方法表有Code屬性存在乔宿,那么它的結(jié)構(gòu)如表6-15.

? ? 表6-15 Code屬性表結(jié)構(gòu)

? ? attribute_name_index是一項指向CONSTANT_Utf8_info型常量的索引位迂,常量值固定位“Code”,它代表了該屬性的屬性名稱详瑞,attribute_length指示了屬性值的長度掂林,由于屬性名稱索引與屬性長度一共為6個字節(jié),所以屬性值的長度固定位整個屬性表長度減去6個字節(jié)坝橡。

? ? max_stack代表了操作數(shù)棧(Operand Stack)深度的最大值泻帮。在方法執(zhí)行的任意時刻,操作數(shù)棧都不會超過這個深度驳庭。虛擬機運行的時候需要根據(jù)這個值來分配棧幀(Stack Frame)中的操作棧深度刑顺。

? ? max_locals代表了局部變量表所需要的存儲空間氯窍。在這里饲常,max_locals的單位是Slot,Slot是虛擬機為局部變量分配內(nèi)存所使用的最小單位狼讨。

? ? code_length和code用來存儲Java源程序編譯后生成的字節(jié)碼指令贝淤。code_length代表字節(jié)碼長度,code是用于存儲字節(jié)碼指令的一系列字節(jié)流政供。

? ? Code屬性是class文件中最重要的一個屬性播聪。

? ? Exceptions屬性朽基,作用是列舉出方法中可能拋出的受檢查異常(Checked Exception),也就是方法描述時在throws關(guān)鍵字后面列舉異常离陶。LineNumberTable屬性稼虎,用于描述Java源碼行號與字節(jié)碼行號之間的對應(yīng)關(guān)系。LocalVariableTable屬性招刨,用于描述棧幀中局部變量表中的變量與Java源碼中定義的變量之間的關(guān)系霎俩。SourceFile屬性,用于記錄生成這個Class文件的源碼文件名稱沉眶。ConstantValue屬性的作用是通知虛擬機自動為靜態(tài)變量賦值打却。只有被static關(guān)鍵字修飾的變量才可以使用這項屬性。InnerClasses屬性用于記錄內(nèi)部類與宿主類之間的關(guān)聯(lián)谎倔。Deprecated以及Synthetic兩個屬性都屬于標(biāo)志類型的布爾屬性柳击,只存在有和沒有的區(qū)別,沒有屬性值的概念片习。StackMapTable屬性捌肴,它是一個復(fù)雜的變長屬性,位于Code屬性的屬性表中毯侦。Signature屬性哭靖,它是一個可選的定長屬性,可以出現(xiàn)在類侈离、字段表和方法表結(jié)構(gòu)的屬性表中试幽。BootstrapMethods屬性,它是一個復(fù)雜的變長屬性卦碾,位于類文件的屬性表中铺坞。

? ? ? 以上內(nèi)容就是java字節(jié)碼文件的結(jié)構(gòu),java字節(jié)碼還有字節(jié)碼指令洲胖,這里就不多贅述了济榨。有興趣可看《深入Java虛擬機-JVM高級特性與最佳實踐》---周志華這本書,挺不錯的绿映。

本文來自于《深入Java虛擬機-JVM高級特性與最佳實踐》---周志明擒滑。如果侵權(quán),請聯(lián)系作者刪除叉弦。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末丐一,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子淹冰,更是在濱河造成了極大的恐慌库车,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,651評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件樱拴,死亡現(xiàn)場離奇詭異柠衍,居然都是意外死亡洋满,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評論 3 392
  • 文/潘曉璐 我一進店門珍坊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來牺勾,“玉大人,你說我怎么就攤上這事阵漏∏葑睿” “怎么了?”我有些...
    開封第一講書人閱讀 162,931評論 0 353
  • 文/不壞的土叔 我叫張陵袱饭,是天一觀的道長川无。 經(jīng)常有香客問我,道長虑乖,這世上最難降的妖魔是什么懦趋? 我笑而不...
    開封第一講書人閱讀 58,218評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮疹味,結(jié)果婚禮上仅叫,老公的妹妹穿的比我還像新娘。我一直安慰自己糙捺,他們只是感情好诫咱,可當(dāng)我...
    茶點故事閱讀 67,234評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著洪灯,像睡著了一般坎缭。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上签钩,一...
    開封第一講書人閱讀 51,198評論 1 299
  • 那天掏呼,我揣著相機與錄音,去河邊找鬼铅檩。 笑死憎夷,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的昧旨。 我是一名探鬼主播拾给,決...
    沈念sama閱讀 40,084評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼兔沃!你這毒婦竟也來了蒋得?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,926評論 0 274
  • 序言:老撾萬榮一對情侶失蹤粘拾,失蹤者是張志新(化名)和其女友劉穎窄锅,沒想到半個月后创千,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體缰雇,經(jīng)...
    沈念sama閱讀 45,341評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡入偷,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,563評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了械哟。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片疏之。...
    茶點故事閱讀 39,731評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖暇咆,靈堂內(nèi)的尸體忽然破棺而出锋爪,到底是詐尸還是另有隱情,我是刑警寧澤爸业,帶...
    沈念sama閱讀 35,430評論 5 343
  • 正文 年R本政府宣布其骄,位于F島的核電站,受9級特大地震影響扯旷,放射性物質(zhì)發(fā)生泄漏拯爽。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,036評論 3 326
  • 文/蒙蒙 一钧忽、第九天 我趴在偏房一處隱蔽的房頂上張望毯炮。 院中可真熱鬧,春花似錦耸黑、人聲如沸桃煎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽为迈。三九已至,卻和暖如春缺菌,著一層夾襖步出監(jiān)牢的瞬間曲尸,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評論 1 269
  • 我被黑心中介騙來泰國打工男翰, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留另患,地道東北人。 一個月前我還...
    沈念sama閱讀 47,743評論 2 368
  • 正文 我出身青樓蛾绎,卻偏偏與公主長得像昆箕,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子租冠,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,629評論 2 354

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