本篇咱們繼續分析Class文件結構的方法及屬性部份內容,上節內容回顧請查看:java
package chapter6;
public class TestClass {
private int m;
public int inc() {
return m + 1;
}
}
複製代碼
使用JDK1.8編譯成class文件,而後經過WinHex打開this
上節咱們分析到字段部分,字段的完整地址範圍:000000E1~000000EA。spa
跟在字段後面的是方法,下面繼續分析。3d
類型:u2
字節地址:000000EB~000000EC
值:0x0002code
說明當前類有2個方法。cdn
類型:u2
字節地址:000000ED~000000EE
值:0x0001對象
查表獲得對應的訪問標誌爲ACC_PUBLIC。blog
類型:u2
字節地址:000000EF~000000F0
值:0x0007索引
對應常量池中的第7項常量,值爲<init>
,即實例初始化方法。
類型:u2
字節地址:000000F1~000000F2
值:0x0008
對應常量池中的第8項常量,值爲()V,說明該方法無參數,返回類型爲void。
由前3項可知,第1個方法爲類的實例初始化方法。
類型:u2
字節地址:000000F3~000000F4
值:0x0001
說明該字段有1個屬性。
屬性的通用格式以下:
類型:u2
字節地址:000000F5~000000F6
值:0x0009
對應常量池中的第9項常量,值爲Code。
類型:u4
字節地址:000000F7~000000FA
值:0x0000002F
將0x0000002F轉換爲十進制,計算獲得47。
類型:u2
字節地址:000000FB~000000FC
值:0x0001
即最大深度爲1。操做數棧的最大深度,由編譯期決定。
類型:u2
字節地址:000000FD~000000FE
值:0x0001
即局部變量的個數爲1。局部變量的個數,由編譯期決定。
max_locals的單位是Slot,Slot是虛擬機爲局部變量分配內存所使用的最小單位。對於長度不超過32位的數據類型,每一個局部變量佔用1個Slot。而double和long的數據類型長度爲64位,須要佔用兩個Slot。
類型:u4
字節地址:000000FF~00000102
值:0x00000005
類型:u1
長度/字節數:5
字節地址:00000103~00000107
其中,第0、一、4字節爲字節碼指令,第二、3字節爲參數索引。
常量池
實例初始化方法字節碼指令信息
其中,初始化方法是沒有參數的,但args_size爲1。這實際上是由於對於非static方法,編譯器默認會將指向當前對象的this做爲方法的第一個參數,以便在調用方法的時候使用。
類型:u2
字節地址:00000108~00000109
值:0x0000
說明沒有異常表信息。
無
類型:u2
字節地址:0000010A~0000010B
值:0x0002
說明該字段有2個屬性。
名稱索引(attribute_name_index)
類型:u2
字節地址:0000010C~0000010D
值:0x000C
對應常量池中的第12項常量,值爲LineNumberTable,即字節碼與源碼的行號信息。
LineNumberTable屬性值的長度(attribute_length)
類型:u4
字節地址:0000010E~00000111
值:0x00000006
LineNumberTable行號表的長度(line_number_table_length)
類型:u2
字節地址:00000112~00000113
值:0x0001
字節碼與源碼行號(字節地址:00000114~00000117)
名稱索引(attribute_name_index)
類型:u2
字節地址:00000118~00000119
值:0x000D
對應常量池中的第13項常量,值爲LocalVariableTable,即方法的本地變量表信息。
LocalVariableTable屬性值的長度(attribute_length)
類型:u4
字節地址:0000011A~0000011D
值:0x0000000C
將0x0000000C轉換爲十進制,計算獲得12。
LocalVariableTable局部變量表的長度(local_variable_table_length)
類型:u2
字節地址:0000011E~0000011F
值:0x0001
LocalVariableTable第1個局部變量(字節地址:00000120~00000129)
start_pc和length二者結合起來就是這個局部變量在字節碼之中的做用域範圍。
也就是說,這個局部變量爲this,類型爲chapter6/TestClass,存放在局部變量表的第0個Slot,做用域爲code[0]~code[4]。
第1個方法對應的字節內容
類型:u2
字節地址:0000012A~0000012B
值:0x0001
查表獲得對應的訪問標誌爲ACC_PUBLIC。
類型:u2
字節地址:0000012C~0000012D
值:0x0010
對應常量池中的第16項常量,值爲inc,正是咱們定義的實例方法名。
類型:u2
字節地址:0000012E~0000012F
值:0x0011
對應常量池中的第17項常量,值爲()I,說明該方法無參數,返回類型爲int。
以上3項,說明該方法定義爲public int inc()。
類型:u2
字節地址:00000130~00000131
值:0x0001
說明該字段有1個屬性。
類型:u2
字節地址:00000132~00000133
值:0x0009
對應常量池中的第9項常量,值爲Code。
類型:u4
字節地址:00000134~00000137
值:0x00000031
將0x00000031轉換爲十進制,計算獲得49。
類型:u2
字節地址:00000138~00000139
值:0x0002
即最大深度爲2。
類型:u2
字節地址:0000013A~0000013B
值:0x0001
即局部變量的個數爲1。
類型:u4
字節地址:0000013C~0000013F
值:0x00000007
類型:u1
長度/字節數:7
字節地址:00000140~00000146
其中,第0、一、四、五、6字節爲字節碼指令,第二、3字節爲參數索引。
常量池
實例初始化方法字節碼指令信息
類型:u2
字節地址:00000147~00000148
值:0x0000
說明沒有異常表信息。
無
類型:u2
字節地址:00000149~0000014A
值:0x0002
說明該字段有2個屬性。
名稱索引(attribute_name_index)
類型:u2
字節地址:0000014B~0000014C
值:0x000C
對應常量池中的第12項常量,值爲LineNumberTable。
值爲LineNumberTable屬性值的長度(attribute_length)
類型:u4
字節地址:0000014D~00000150
值:0x00000006
值爲LineNumberTable行號表的長度(line_number_table_length)
類型:u2
字節地址:00000151~00000152
值:0x0001
字節碼與源碼行號(字節地址:00000153~00000156)
名稱索引(attribute_name_index)
類型:u2
字節地址:00000157~00000158
值:0x000D
對應常量池中的第13項常量,值爲LocalVariableTable。
LocalVariableTable屬性值的長度(attribute_length)
類型:u4
字節地址:00000159~0000015C
值:0x0000000C
將0x0000000C轉換爲十進制,計算獲得12。
LocalVariableTable局部變量表的長度(local_variable_table_length)
類型:u2
字節地址:0000015D~0000015E
值:0x0001
LocalVariableTable第1個局部變量(字節地址:0000015F~00000168)
start_pc和length二者結合起來就是這個局部變量在字節碼之中的做用域範圍。
也就是說,這個局部變量爲this,類型爲chapter6/TestClass,存放在局部變量表的第0個Slot,做用域爲code[0]~code[6]。
第2個方法對應的字節內容
類型:u2
字節地址:00000169~0000016A
值:0x0001
說明該類有1個屬性。
類型:u2
字節地址:0000016B~0000016C
值:0x0014
對應常量池中的第12項常量,值爲SourceFile,即class文件的Java源文件名稱。
類型:u4
字節地址:0000016D~00000170
值:0x00000002
類型:u2
字節地址:00000171~00000172
值:0x0015
對應常量池中的第21項常量,值爲TestClass.java。
字節碼內容
參考
《Java虛擬機規範》(Java SE 8版)
《深刻理解Java虛擬機 JVM高級特性與最佳實踐》
更多文章,請關注公衆號:二進制之路