JVM系列:(五).class檔案結構
原文連結: JVM系列:(五).class檔案結構
各種不同平臺的虛擬機器與所有平臺都統一使用的程式儲存格式---位元組碼(ByteCode)是構成平臺無關性的基石。
一 .class檔案的來源
計算機只認識0和1,所以我們寫的程式需要被編譯器翻譯成由0和1構成的二進位制格式才能被計算機執行。
JVM只認識.class位元組碼,所以想要在JVM上執行的所有語言都需要編譯為JVM能識別的位元組碼格式。
二 具體結構
2.1 結構
整個 class 檔案的結構基本保持了我們編寫 java 原始碼程式的上下結構,其本質上就是一張表,如果所示:
名稱 | 數量 | 描述 |
---|---|---|
magic | 1 | 魔數 |
minor_version | 1 | 次版本號 |
major_version | 1 | 主版本號 |
constant_pool_count | 1 | 常量池中常量的個數 |
constant_pool | constant_pool_count-1 | 常量池 |
access_flags | 1 | 訪問標誌 |
this_class | 1 | 類索引 |
super_class | 1 | 父類索引 |
interfaces_count | 1 | 介面索引集合容量大小 |
interfaces | interfaces_count | 介面索引集合 |
fields_count | 1 | 欄位表集合容量大小 |
fields | fields_count | 欄位表集合 |
methods_count | 1 | 方法表集合容量大小 |
methods | methods_count | 方法表集合 |
attributes_count | 1 | 屬性表集合容量大小 |
attributes | attributes_count | 屬性表集合 |
2.2 描述
- 魔數:它的唯一作用是用於確定這個檔案是否為一個能被虛擬機器接受的class檔案。使用魔數而不是副檔名來進行識別主要是基於安全考慮,因為副檔名可以很隨意的被改動。
- 次版本號:class 檔案的版本號。
- 主版本號:class 檔案的版本號,每個JDK大版本的釋出,主版本號都會向上加1,高版本的JDK能向下相容以前版本的class檔案,但不能執行以後版本的class檔案。
- 常量池中常量的個數:由於常量池中常量的數量是不固定的,所以在常量池的入口需要設定一個數據表面常量池容量大小。
- 常量池:常量池主要存放兩大類常量,字面量和符合引用。字面量比較接近於Java語言層面的常量概念,如文字字串、被宣告為final的常量值等。而符號引用則包含三類常量(1:類和介面的全限定名、2:欄位的名稱和描述符、3:方法的名稱和描述符)。
- 訪問標誌:這個標誌用於識別一些類或介面的訪問資訊,包括:這個class是類還是介面;是否定義為public型別;是否定義為abstract型別;如果是類的話,是否被宣告為final等等。
- 類索引:用於確定這個類的全限定名。
- 父類索引:用於確定這個類的父類的全限定名。由於Java語言不容許多重繼承,所以父類索引只有一個,除了 java.lang.Object 外,所有的Java類都有父類,因此除了 java.lang.Object 外,所有Java類的父類索引都不為0.
- 介面索引集合容量大小:用於表示介面索引集合的容量大小。
- 介面索引集合:用來描述這個類實現了哪些介面,這些被實現的介面將按 implements 語句(如果這個類是一個介面,則應當是 extends 語句)後的介面順序從左到右排列在介面的索引集合中。
- 欄位表集合容量大小:用於表示欄位表集合的容量大小
- 欄位表集合:用於描述介面或類中聲名的變數,包括了類級變數或例項級變數,但不包括在方法內部宣告的變數。包括以下資訊:欄位的作用域(public、private、protected修飾符)、是類級變數還是例項級變數(static修飾符)、可變性(final)、併發可見性(volatile修飾符,是否強制從主記憶體讀寫)、欄位名稱等。
- 方法表集合容量大小:用於表示方法表集合的容量大小
- 方法表集合:用於表示類或介面中定義的方法。和欄位表集合類似。
- 屬性表集合容量大小:用於表示屬性表集合的容量大小
- 屬性表集合:在class檔案、欄位表、方法表中都可以攜帶自己的屬性表集合,以用於描述某些場景專有的資訊。
三 總結
class檔案是Java虛擬機器執行引擎的資料入口,也是Java技術體系的基礎支柱之一。瞭解class檔案的結構對後面進一步瞭解虛擬機器執行引擎有很重要的意義。
接下來我們將介紹:
- JVM類載入步驟

掃碼關注有驚喜