1. 程式人生 > >JVM學習筆記(二)

JVM學習筆記(二)

上次我們分析了常量池,根據class檔案格式,我們看到常量池後面是access flag訪問標誌,用於表示這個class檔案代表的類的訪問相關資訊,比如是public還是private,是final或者abstract,還有最重要的,是類還是介面等等。具體見下圖(圖片來源網路)

在這裡插入圖片描述

訪問標誌是個U2型別,在我們的例子中,這裡的值為0x0021,根據上圖,正好是0x0001 & 0x0020的結果,所以該標誌位表示的就是ACC_PUBLICACC_SUPERACC_PUBLIC即public,ACC_SUPER如上圖的解釋,在jdk1.2之後編譯出來的類該標誌都為真,目前我們先不用深究。

接下來是一個U2的this_class

,表示當前類,它指向一個CONSTANT_CLASS_INFO,在例子中該數值為0x0005,從上篇文章的分析中我們可以看到該值為“First”。如下圖

在這裡插入圖片描述

在這裡插入圖片描述

同理,對於下一個super_class也一樣,它表示父類,在本例中它的值是0x0006,根據上篇分析,它對應的值是java/lang/Object。除了Object類所有的類都有父類,所以只有Object類的super_class的值為0,其他類都不為0。

接下來是interfaces_count表示有多少介面。在本列中沒有實現介面,所以這值為0x0000,也就是說後面沒有interfaces這個屬性。

接下來是fields_count,表示欄位表集合。這裡fields_count

的值為0x0000表示沒有fields

接下來是method_count,表示方法表集合,它的值為0x0002,表示有兩個方法methodsmethods的格式如下圖(圖片來源

在這裡插入圖片描述

首先是一個U2的access_flags,它的內容和前面說的常量池後面的access_flags差不多,它代表的內容如下圖(圖片來源

在這裡插入圖片描述

我們例子中的值為0x0001,即為public。

接下來是name_index 0x0007,指向常量池第七個引數,即。
descriptor_index 0x0008,指向常量池第八個引數,即()V。這兩個引數表示我們例子中的First類的構造方法,例子中沒有寫構造方法,所以First會使用預設的java/lang/Object的構造方法,沒有引數,返回void。

接下來是attributes_count 0x0001,表示有一個屬性表,屬性表通常的結構如下圖(來源地址

在這裡插入圖片描述

屬性表第一個是屬性表的名稱attribute_name_index,在例子中的值為0x0009,指向常量池中的#9,即Code(每一個屬性表的名稱都會指向常量池)。

java方法體中的程式碼都儲存在Code屬性表中

Code屬性表的結構如下圖(圖片來源與上圖一樣)
在這裡插入圖片描述

attribute_length U4 001d 29 屬性表長度
max_stack U2 0001 1 運算元棧最大深度
max_locals U2 0001 1 區域性變量表所需儲存空間
code_length U4 0000 0005 5 位元組碼長度
code U1 位元組碼 值如下
2a aload_0
b7 invokespecial
0001 invokespecial的引數 #1 java/lang/Object.;<>V
b1 return
這裡表示執行了物件的初始化工作,具體位元組碼的執行部分我們後面再分析。
exception_table_length U2 0000 0 異常長度
由於長度為0所以這裡沒有exception_table
接下來又是一個屬性表,大家可以試著自己分析,這個屬性表為LineNumberTable,用於描述位元組碼和原始碼之間的關係,也就是程式報錯後可以讓我們看到到底是哪行報的錯。結構如下圖(來源同上)
在這裡插入圖片描述

line_number_info的結構如下

start_pc u2
line_number u2

到此方法表分析完畢,對比檔案格式表,我們看到方法表之後又是一個attirbutes_count,那我們重複上述工作繼續。
attributes_count的值為0001,表示有一個屬性表
attribute_name_index的值為000d即13,指向常量池的第十三個值,即SourceFile。SourceFile用於記錄生成這個class檔案的原始碼檔名稱,它的結構如下

attribute_name_index u2
attribute_length u4
sourcefile_index u2

按照格式分析如下
attribute_length 0000 0002,表示該屬性有兩個位元組,即000e。
sourcefile_index 000e 即14,指向常量池第十四個值,即First.java

至此整個helloworld就分析完了,有不對的地方歡迎大家指正
.