目錄
- 一、概述
- 二、Class 檔案結構總結
- 1.魔數
- 2.Class檔案版本
- 3.常量池
- 4.訪問標志
- 5.當前類索引,父類索引與介面索引集合
- 6.欄位表集合
- 7.方法表集合
- 8.屬性表集合
一、概述
在 Java 中,JVM 可以理解的代碼就叫做 位元組碼 (即擴展名為 .class 的檔案),它不面向任何特定的處理器,只面向虛擬機,Java 語言通過位元組碼的方式,在一定程度上解決了傳統解釋型語言執行效率低的問題,同時又保留了解釋型語言可移植的特點,所以 Java 程式運行時比較高效,而且,由于位元組碼并不針對一種特定的機器,因此,Java 程式無須重新編譯便可在多種不同作業系統的計算機上運行,
Clojure(Lisp 語言的一種方言)、Groovy、Scala 等語言都是運行在 Java 虛擬機之上,下圖展示了不同的語言被不同的編譯器編譯成 .class 檔案最終運行在 Java 虛擬機之上, .class 檔案的二進制格式可以使用 [WinHex]查看,

可以說 .class 檔案是不同的語言在 Java 虛擬機之間的重要橋梁,同時也是支持 Java 跨平臺很重要的一個原因,
參考資料:《Java中高級核心知識全面決議》
有想要獲取這份學習資料的同學可以點擊這里免費獲取
二、Class 檔案結構總結
根據 Java 虛擬機規范,類檔案由單個 ClassFile 結構組成:
ClassFile {
u4 magic; //Class 檔案的標志
u2 minor_version;//Class 的小版本號
u2 major_version;//Class 的大版本號
u2 constant_pool_count;//常量池的數量
cp_info constant_pool[constant_pool_count-1];//常量池
u2 access_flags;//Class 的訪問標記
u2 this_class;//當前類
u2 super_class;//父類
u2 interfaces_count;//介面
u2 interfaces[interfaces_count];//一個類可以實作多個介面
u2 fields_count;//Class 檔案的欄位屬性
field_info fields[fields_count];//一個類會可以有個欄位
u2 methods_count;//Class 檔案的方法數量
method_info methods[methods_count];//一個類可以有個多個方法
u2 attributes_count;//此類的屬性表中的屬性數
attribute_info attributes[attributes_count];//屬性表集合
}
下面詳細介紹一下 Class 檔案結構涉及到的一些組件,
Class檔案位元組碼結構組織示意圖 (之前在網上保存的,非常不錯,原出處不明):

1.魔數
u4 magic; //Class 檔案的標志
每個 Class 檔案的頭四個位元組稱為魔數(Magic Number),它的唯一作用是確定這個檔案是否為一個能被虛擬機接收的 Class 檔案,
程式設計者很多時候都喜歡用一些特殊的數字表示固定的檔案型別或者其它特殊的含義,
2.Class檔案版本
u2 minor_version;//Class 的小版本號
u2 major_version;//Class 的大版本號
緊接著魔數的四個位元組存盤的是 Class 檔案的版本號:第五和第六是次版本號,第七和第八是主版本號,
高版本的 Java 虛擬機可以執行低版本編譯器生成的 Class 檔案,但是低版本的 Java 虛擬機不能執行高版本編譯器生成的 Class 檔案,所以,我們在實際開發的時候要確保開發的的 JDK 版本和生產環境的JDK 版本保持一致,
3.常量池
u2 constant_pool_count;//常量池的數量
cp_info constant_pool[constant_pool_count-1];//常量池
緊接著主次版本號之后的是常量池,常量池的數量是 constant_pool_count-1(常量池計數器是從1開始計數的,將第0項常量空出來是有特殊考慮的,索引值為0代表“不參考任何一個常量池項”),
常量池主要存放兩大常量:字面量和符號參考,字面量比較接近于 Java 語言層面的的常量概念,如文本字串、宣告為 final 的常量值等,而符號參考則屬于編譯原理方面的概念,包括下面三類常量:
- 類和介面的全限定名
- 欄位的名稱和描述符
- 方法的名稱和描述符
常量池中每一項常量都是一個表,這14種表有一個共同的特點:開始的第一位是一個 u1 型別的標志位-tag 來標識常量的型別,代表當前這個常量屬于哪種常量型別.


.class 檔案可以通過 javap -v class類名 指令來看一下其常量池中的資訊( javap -v class類名-> temp.txt :將結果輸出到temp.txt 檔案),
4.訪問標志
在常量池結束之后,緊接著的兩個位元組代表訪問標志,這個標志用于識別一些類或者介面層次的訪問資訊,包括:這個 Class 是類還是介面,是否為 public 或者 abstract 型別,如果是類的話是否宣告為final 等等,
類訪問和屬性修飾符:

我們定義了一個Employee 類
package top.snailclimb.bean;
public class Employee {
...
}
通過 javap -v class類名 指令來看一下類的訪問標志,

5.當前類索引,父類索引與介面索引集合
u2 this_class;//當前類
u2 super_class;//父類
u2 interfaces_count;//介面
u2 interfaces[interfaces_count];//一個類可以實作多個介面
類索參考于確定這個類的全限定名,父類索參考于確定這個類的父類的全限定名,由于 Java 語言的單繼承,所以父類索引只有一個,除了 java.lang.Object 之外,所有的 java 類都有父類,因此除了java.lang.Object 外,所有 Java 類的父類索引都不為 0,
介面索引集合用來描述這個類實作了那些介面,這些被實作的介面將按 implents (如果這個類本身是介面的話則是 extends ) 后的介面順序從左到右排列在介面索引集合中,
6.欄位表集合
u2 fields_count;//Class 檔案的欄位的個數
field_info fields[fields_count];//一個類會可以有個欄位
欄位表(field info)用于描述介面或類中宣告的變數,欄位包括類級變數以及實體變數,但不包括在方法內部宣告的區域變數,
field info(欄位表) 的結構:

- access_flags: 欄位的作用域(
public,private,protected修飾符),是實體變數還是類變數(static修飾符),可否被序列化(transient 修飾符),可變性(final),可見性(volatile 修飾符,是否強制從主記憶體讀寫), - name_index: 對常量池的參考,表示的欄位的名稱;
- descriptor_index: 對常量池的參考,表示欄位和方法的描述符;
- attributes_count: 一個欄位還會擁有一些額外的屬性,
attributes_count存放屬性的個數; - attributes[attributes_count]: 存放具體屬性具體內容,
上述這些資訊中,各個修飾符都是布林值,要么有某個修飾符,要么沒有,很適合使用標志位來表示,而欄位叫什么名字、欄位被定義為什么資料型別這些都是無法固定的,只能參考常量池中常量來描述,
欄位的 access_flags 的取值:

7.方法表集合
u2 methods_count;//Class 檔案的方法的數量
method_info methods[methods_count];//一個類可以有個多個方法
methods_count 表示方法的數量,而 method_info 表示的方法表,
Class 檔案存盤格式中對方法的描述與對欄位的描述幾乎采用了完全一致的方式,方法表的結構如同欄位表一樣,依次包括了訪問標志、名稱索引、描述符索引、屬性表集合幾項,
method_info(方法表的) 結構:

方法表的 access_flag 取值:

注意:因為 volatile 修飾符和 transient 修飾符不可以修飾方法,所以方法表的訪問標志中沒有這兩個對應的標志,但是增加了 synchronized 、 native 、 abstract 等關鍵字修飾方法,所以也就多了這些關鍵字對應的標志,
8.屬性表集合
u2 attributes_count;//此類的屬性表中的屬性數
attribute_info attributes[attributes_count];//屬性表集合
在 Class 檔案,欄位表,方法表中都可以攜帶自己的屬性表集合,以用于描述某些場景專有的資訊,與Class 檔案中其它的資料專案要求的順序、長度和內容不同,屬性表集合的限制稍微寬松一些,不再要求各個屬性表具有嚴格的順序,并且只要不與已有的屬性名重復,任何人實作的編譯器都可以向屬性表中寫 入自己定義的屬性資訊,Java 虛擬機運行時會忽略掉它不認識的屬性,
參考資料:《Java中高級核心知識全面決議》
有想要獲取這份學習資料的同學可以點擊這里免費獲取
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/234889.html
標籤:其他
上一篇:SQL——知識入門
