【JVM】深入解析class類檔案

duanhao發表於2021-09-09

眾所周知,我們在執行java程式碼時,首先java檔案會被編譯成class檔案,然後將class檔案裝載到java虛擬機器中。那麼這個class檔案到底是什麼呢,今天我們就來分析一下。


首先編寫一個測試類Test,內容很簡單,就是輸出“hello,world”


圖片描述

Test類

圖片描述

java檔案以及編譯生成的class檔案


使用WinHex工具開啟這個Test.class檔案,會發現class檔案內容是這樣的:


圖片描述

class檔案內容的一部分

觀察這些資料,不難發現,class檔案是一組以8位位元組為基本單位的二進位制流,各個資料專案嚴格地按順序排列在一起,中間沒有空隙。

那麼圖中這些16進位制資料代表什麼含義呢?

1.每個class檔案開頭的4個位元組稱為“魔數”,即圖中的“CA FE BA BE”,(一個16進位制數代表4位,兩個就是8位,剛好是一個位元組),這個魔數的作用就是:確定這個檔案是否是一個能被JVM接受的class檔案。

2.緊接著魔數的4個位元組是Class檔案的版本號,其中5、6兩個位元組是次版本號(0x0000),7和8兩個位元組是主版本號(0x0035),也即10進位制中的53,代表這個檔案是能被jdk1.8或以上版本虛擬機器執行的class檔案。

3.再往後,就是常量池的入口常量池可以理解成class檔案中的資源倉庫。在java中有三種常量池:String常量池、執行時常量池和class常量池。而我們這裡講的就是class常量池,class常量池主要存放字面量和符號引用,由於不同class檔案常量池中的常量數是不同的,所以會有兩個位元組表示常量池計數器,記錄了常量的個數。這裡是001E,是十進位制中的30,表示有29項常量(第0項常量是空出來的)。緊接著後面的0A,是常量池第一項常量的標誌位,屬於CONSTANT_Methodref_info型別,代表類中方法的符號引用。其後的16進位制數以此類推。

4.在常量池結束以後的兩個位元組代表訪問標誌,用於識別一些類或介面層次的訪問資訊。比如,這個class是類還是介面,是否定義成public等。

5.訪問標誌後面是類索引、父類索引和介面索引集合,class檔案由這三項資料來確定這個類的繼承關係。類索引確定這個類的全限定名,父類索引確定這個類的父類的全限定名,由於Object是所有java類的父類,所以除了Object之外,任何類的父類索引都不為0.介面索引集合描述這個類實現了哪些介面。

6.而在後面的是欄位表集合、方法表集合和屬性表集合,此處就不再做說明,如果有對這些感興趣的,可以去查閱資料書,推薦周志明的《深入理解java虛擬機器》(非打廣告)



作者:封心_SH
連結:


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/1343/viewspace-2818143/,如需轉載,請註明出處,否則將追究法律責任。

相關文章