Java 類檔案結構是一個二進制位元組流,由 Java 虛拟機解釋。
編譯後的class檔案用編輯器16進制打開,類似下圖的樣子,1個16進制是4位,2個16進制是1個位元組。
前幾位一般都一樣,CA FE BA BE,為魔術值 Magic Number,占四個位元組。
第二部分為版本号,Minor Version 兩個位元組,Major Version 兩個位元組,例子裡的34換成10進制為52,表示JDK8。
第三部分為常量池中個數, constant_pool_count,008D(141),兩個位元組,存儲(141-1)個資料;緊接着個數,就是具體的常量池中存儲的内容,占用位元組個數完全由常量個數和每個常量代表的類型決定。
access_flag,目前類 class 的通路修飾符,例如 public 或者 private,兩個位元組。
this_class,目前這個類是什麼,存在常量池中。
super_class,父類是什麼,存在常量池中。
interface_count,實作的接口的個數。
interfaces,具體的實作接口。
fields_count,屬性個數。
fields,具體的屬性。
method_count,方法個數。
method_info,方法。
attribute_count,附加屬性個數。
attribute,附加屬性。
可以使用javap -v classfile_full_path java自帶指令檢視,或者安裝 IDEA插件,JClassLib 來分析 class檔案内容,使用後者檢視更清晰,效果是這樣的:
General Information 給出了概要資訊,存儲各項内容的數量,展開各個節點,左側各節點裡面的存儲内容和右側給的數量是一緻的。
用這個結合之前的編輯器16進制檢視位元組碼,更容易讀懂位元組碼。
1、常量池閱讀方法,位元組碼中008D,表示常量池中存儲140個資料,對比IDEA中顯示的内容:
省略部分常量池内容,一直拖到最後,
看常量池中第一個内容,
class name 占位常量池中28号,name and type占位74号,對比位元組碼中内容:
0A(10)為标志位,001C(28);004A(74)
繼續往後看位元組碼,依舊是0A,對應Constan Pool中的第二項:
[002] CONSTANT_Mehotdref_info。
讀懂常量池的關鍵點在于标志位對應的存儲資料類型和長度,這個可以從jvms- java 虛拟機規範中找到說明,如下圖,标志位1個位元組,左邊一清單示類型,右列為對應的10進制數值。
2、methods 的閱讀方法
method_info 結構格式如下,方法修飾符,名字索引,描述符索引,附加屬性:
對比 JclassLib 解釋:
附加屬性,最重要的一項是Code,代碼實作,右側的Bytecode為代碼編譯後的位元組碼指令組成,如下圖,可以參考指令說明進一步了解。
參考指令說明,找到位元組碼對應位置:
還有好多内容,後面有時間再記錄。