JVM之Class文件的組成結構

Class 文件的組成結構

當你用16進制編譯器打開一個java文件,你就能夠看到相似這個的Java文件的模板。 java

什麼是class文件?

Class 文件是一組以 8 位字節爲基礎單位的二進制流,各個數據項目嚴格按照順序緊湊地排列在 Class 文件中,中間沒有任何分隔符。Java 虛擬機規範規定 Class 文件採用一種相似 C 語言結構體的僞結構來存儲數據,這種僞結構中只有兩種數據類型:無符號數和表,咱們以後也主要對這兩種類型的數據類型進行解析。程序員

  • 無符號數: 無符號數屬於基本數據類型,以 u一、u二、u四、u8 分別表明 1 個字節、2 個字節、4 個字節和 8 個字節的無符號數,能夠用它來描述數字、索引引用、數量值或 utf-8 編碼的字符串值。
  • 表: 表是由多個無符號數或其餘表爲數據項構成的複合數據類型,名稱上都以 _info 結尾。

JAVA程序員的浪漫

Class 文件的頭 8 個字節是魔數(magic number )和版本號,其中頭 4 個字節是魔數,也就是 0xCAFEBABE,它能夠用來肯定這個文件是否爲一個能被虛擬機接受的 Class 文件(這經過擴展名來識別文件類型要安全,畢竟擴展名是能夠隨便修改的)。

後 4 個字節則是當前 Class 文件的版本號,其中第 五、6 個字節是次版本號,第 七、8 個字節是主版本號。安全

網上摘取一篇講述CAFEBABE的小故事關於CAFEBABE:

常量池

從第 9 個字節開始,就是常量池的入口,常量池是 Class 文件中:編碼

  • 與其餘項目關聯最多的的數據類型;
  • 佔用 Class 文件空間最大的數據項目;
  • Class 文件中第一個出現的表類型數據項目。

常量池的開始的兩個字節,也就是第 九、10 個字節,放置一個 u2 類型的數據,標識常量池中常量的數量 cpc (constant_pool_count),這個計數值有一個十分特殊的地方,就是它是從 1 開始而不是從 0 開始的,也就是說若是 cpc = 22,那麼表明常量池中有 21 項常量,索引值爲 1 ~ 21,第 0 項常量被空出來,爲了知足後面某些指向常量池的索引值的數據在特定狀況下須要表達「不引用任何一個常量池項目」時,將讓這個索引值指向 0 便可。spa

常量池中記錄的是代碼出現過的全部 token(類名,成員變量名等,也是咱們接下來要修改的地方)以及符號引用(方法引用,成員變量引用等),主要包括如下兩大類常量:3d

  • 字面量: 接近於 Java 語言層面的常量概念,包括
    • 文本字符串
    • 聲明爲 final 的常量值
  • 符號引用: 以一組符號來描述所引用的目標,包括
    • 類和接口的全限定名
    • 字段的名稱和描述符
    • 方法的名稱和描述符

常量池中的每一項常量都經過一個表來存儲。目前一共有 14 種常量,不過麻煩的地方就在於,這 14 種常量類型每一種都有本身的結構,咱們在這裏只詳細介紹兩種:CONSTANT_Class_info 和 CONSTANT_Utf8_info。code

CONSTANT_Class_info 的存儲結構爲:cdn

... [ tag=7 ] [ name_index ] ...
... [  1位  ] [     2位    ] ...
複製代碼

其中,tag 是標誌位,用來區分常量類型的,tag = 7 就表示接下來的這個表是一個 CONSTANT_Class_info,name_index 是一個索引值,指向常量池中的一個 CONSTANT_Utf8_info 類型的常量所在的索引值,CONSTANT_Utf8_info 類型常量通常被用來描述類的全限定名、方法名和字段名。它的存儲結構以下:blog

... [ tag=1 ] [ 當前常量的長度 len ] [ 常量的符號引用的字符串值 ] ...
... [  1位  ] [        2位        ] [         len位         ] ...
複製代碼
相關文章
相關標籤/搜索