Java位元組碼結構剖析二:欄位表
access_flags
訪問標誌資訊包括該class檔案是類還是介面,是否定義成public,是否是abstract,如果是類,是否被申明為final。access_flags 的取值範圍和相應含義見下表。
我們的位元組碼裡該位置的16進製表示是0×0021。0×0021=0×0001 ^ 0×0020。即代表該類的訪問修飾是public的。ACC_SUPER這裡不做介紹,看看JVM規範對他的描述,瞭解即可。
ACC_SUPER 標誌用於確定該 Class 檔案裡面的 invokespecial 指令使用的是哪一種執行語義。目前 Java 虛擬機器的編譯器都應當設定這個標誌。ACC_SUPER 標記是為了向後相容舊編譯器編譯的 Class 檔案而存在的,在 JDK1.0.2 版本以前的編譯器產生的 Class 檔案中,access_flag 裡面沒有 ACC_SUPER 標誌。同時,JDK1.0.2 前的 Java 虛擬機器遇到 ACC_SUPER 標記會自動忽略它。
this_class_name
類索引,this_class 的值必須是對 constant_pool 表中專案的一個有效索引值。constant_pool 表在這個索引處的項必須為 CONSTANT_Class_info 型別常量,表示這個 Class 檔案所定義的類或介面。
在我的位元組碼檔案中,該16進位制值為0×0005=5。通過常量池資訊,最終他指向的是一個utf-8字串,com/shengsiyuan/jvm/bytecode/MyTest2。即類的全限定名。
1 2 |
|
父類索引,對於類來說,super_class 的值必須為 0 或者是對 constant_pool 表中專案的一個有效索引值。
在位元組碼檔案中,父類索引為0x000A=10。即父類是 java/lang/Object。
1 2 |
|
介面計數器,interfaces_count 的值表示當前類或介面的直接父介面數量。
我們的程式碼沒有實現任何介面,所以該項值為0,即0×0000。
interfaces[]
介面表,interfaces[]陣列中的每個成員的值必須是一個對 constant_pool 表中專案的一個有效索引值,它的長度為 interfaces_count。
我們程式碼沒有介面,所以我們的位元組碼檔案裡沒有這項了。所以 interfaces_count 後面就直接是欄位計數器和欄位表。
fields_count
欄位計數器,fields_count 的值表示當前 Class 檔案 fields[]陣列的成員個數。也就是當前類的類欄位和例項欄位的個數。
我們原始碼裡定義了3個欄位,1個類欄位,2個例項欄位。所以fields_count為3。檢視對應位元組碼檔案的16進製表示0×0003=3。
fields[]
欄位表用於描述類和介面中宣告的變數。這裡的欄位包含了類級別變數以及例項變數,但是不包括方法內部宣告的區域性變數。
field_info結構格式如下:
1 2 3 4 5 6 7 |
|
access_flags 項的值是用於定義欄位被訪問許可權和基礎屬性的掩碼標誌。access_flags 的取值範圍和相應含義見如下表:
看在我位元組碼中的16進製表示,0×0000=0。0代表沒有修飾符的意思。看我們的原始碼:String str = “Welcome”;,即預設修飾符。
● name_index 項的值必須是對常量池的一個有效索引。常量池在該索引處的項必須是CONSTANT_Utf8_info結構,表示一個有效的欄位的非全限定名。在位元組碼裡是0x000B=11。常量池11處:
1 |
|
表示欄位的名稱為“str”。
● descriptor_index 項的值必須是對常量池的一個有效索引。常量池在該索引處的項必須是CONSTANT_Utf8_info結構,表示一個有效的欄位的描述符。位元組碼中,0x000C=12。看常量池:
1 |
|
表示該欄位是String型別。
在JVM規範中,每個變數/欄位都有描述資訊,描述資訊主要作用是描述欄位的資料型別、方法的引數列表(包括數量,型別與順序)與返回值。根據描述符規則,基本資料型別和代表無返回值的void型別都用一個大寫字元來表示,物件型別則使用字元L加物件的全限定名稱來表示。為了壓縮位元組碼檔案的體積,對於基本資料型別,JVM都只使用一個大寫字母表示,如下所示:B-byte、C-char、D-double、F-float、I-int、J-long、S-short、Z-boolean、V-void、L-物件型別,如Ljava/lang/String。
對於陣列型別來說,每一個緯度使一個前置的[表示,如int[]被記錄為[I,String[][]被記錄為[[Ljava/lang/String;。
在位元組碼裡,0x0000=0。即該欄位沒有附加屬性。
● attributes[]attributes 表的每一個成員的值必須是 attribute結構,一個欄位可以有任意個關聯屬性。
因為該欄位沒有附加屬性,所以這項資料沒有。
以上就是欄位表裡的第1個欄位的完整位元組碼資訊描述。也就是我們定義的『str』欄位的資訊。我們程式碼裡還有2個欄位 private int x = 5 和 public static Integer in = 10。我便不再描述了,大家可以緊接著我後面把這兩個欄位的資訊解析出來。
原文釋出時間為:2018-11-22