- methods
方法表與
field_info
中的屬性表結構相同,方法里的代碼,經過編譯成字節碼指令后,存放在方法屬性表集合中一個Code
屬性中。與字段表集合相對應,如果父類方法在子類中沒有被重寫
,方法表集合中就不會出現
來自父類的方法信息。但同樣,有可能會出現由編譯器自動添加的方法,最典型的的類構造器<clinit>
方法和實例構造器<init>
方法。
重載:java中,重載
一個方法,除了要與原方法具有相同的簡單名稱外,還要擁有一個與原方法不同的特征簽名,特征簽名就是一個方法中各個參數在常量池中的字段符號引用的集合,也就是因為返回值不包含在特征簽名中,所以java無法僅靠返回值不同來對一個方法進行重載。
方法訪問標志
方法表結構
-
Code
結構
- 結構:
屬性名索引(u2,Code)
+屬性值長度(u4)
+屬性值
Code
屬性值結構
max_stack(u2)
+max_locals(u2)
+指令長度(u4)
+指令
+異常表長度(u2,exception_table_length)
+異常表
+屬性表數量(u2)
+屬性表
Code屬性表結構
- 方法表中不一定存在
Code
屬性
Java程序方法體中的代碼經過Javac編譯后,生成的字節碼指令便會存儲在Code屬性中,但并非所有的方法表都必須存在這個屬性,比如接口或抽象類中的方法就
不存在Code屬性
。
max_stack
max_stack
是操作數棧深度的最大值,就是方法調用深度,其值與棧幀大小有關,可能類似于max_stack*棧幀大小=棧
max_locals
Slot的長度與字節的關系
max_locals
代表局部變量表所需的存儲空間,單位是Slot
,并不是在方法中用到了多少局部變量,就把這些局部變量所占Slot之和作為max_locals的值,max_locals<=Code的局部變量表長度(local_variable_table_length)
,是通過局部變量的作用域
計算出來的一個最小的Slot值
,因為局部變量超出作用域就相當于沒用了
,因而可以復用。
max_locals計算
下面是重點:
max_stack
最大棧深度,單位是Slot
max_locals
最大可能使用的
局部變量表的長度
,單位是Slot
- 至少有2種情況可以影響
max_locals
的值
- 方法中的局部變量作用域
如下public class TestClass { public int inc() { { int c=1; c++; } int d=2; d++; return 2; } }
顯然c、d的作用域沒有重合的地方,那么就可以重用。這種方式就可以
減少max_locals
- 存放臨時數據的Slot
例如java class.類結構.例子.通過一個帶Exception的方法對其執行步驟進行詳細解釋中,變量表中有3個變量,而實際上max_slots
為5
這種是增加max_locals
- 異常表結構
根據上面的Exception table
,異常表分為
from(start_pc)
:try
開始的位置
to(end_pc)
:try
結束的位置,不包含
target(handler_pc)
:catch
開始的位置
type(catch_type)
:異常類型,如Class java/lang/Exception
表示Exception類型異常,any
表示所有類型異常處理邏輯如下:
如果當字節碼在第start_pc
到第end_pc
行之間(不包括end_pc
)出現了類型為catch_type
或其子類的異常,則轉到第handler_pc
行繼續處理。當catch_type
為0時,代表所有異常。
行的說明:行是字節碼對于方法體開始的偏移量。
- 異常屬性
與異常表結構區分。
描述的是 throws后面列舉的異常