Java Class文件結構實例分析(下)

本篇咱們繼續分析Class文件結構的方法及屬性部份內容,上節內容回顧請查看:java

Java Class文件結構實例分析(上)數組

Class文件格式信息

image

繼續上節實例代碼

package chapter6;
public class TestClass {
	private int m;
	public int inc() {
		return m + 1;
	}
}
複製代碼

使用JDK1.8編譯成class文件,而後經過WinHex打開this

image

方法

image

image

上節咱們分析到字段部分,字段的完整地址範圍:000000E1~000000EA。spa

跟在字段後面的是方法,下面繼續分析。3d

方法計數器(methods_count)

類型:u2
字節地址:000000EB~000000EC
值:0x0002code

說明當前類有2個方法。cdn

第1個方法

訪問標誌(access_flags)

類型:u2
字節地址:000000ED~000000EE
值:0x0001對象

查表獲得對應的訪問標誌爲ACC_PUBLIC。blog

名稱索引(name_index)

類型:u2
字節地址:000000EF~000000F0
值:0x0007索引

對應常量池中的第7項常量,值爲<init>,即實例初始化方法。

描述符(descriptor_index)

類型:u2
字節地址:000000F1~000000F2
值:0x0008

對應常量池中的第8項常量,值爲()V,說明該方法無參數,返回類型爲void。

由前3項可知,第1個方法爲類的實例初始化方法。

屬性計數器(attributes_count)

類型:u2
字節地址:000000F3~000000F4
值:0x0001

說明該字段有1個屬性。

屬性的通用格式以下:

image

第1個屬性

名稱索引(attribute_name_index)

類型:u2
字節地址:000000F5~000000F6
值:0x0009

對應常量池中的第9項常量,值爲Code。

image

屬性值的長度(attribute_length)

類型:u4
字節地址:000000F7~000000FA
值:0x0000002F

將0x0000002F轉換爲十進制,計算獲得47。

操做數棧的最大深度(max_stack)

類型:u2
字節地址:000000FB~000000FC
值:0x0001

即最大深度爲1。操做數棧的最大深度,由編譯期決定。

局部變量的個數(max_locals)

類型:u2
字節地址:000000FD~000000FE
值:0x0001

即局部變量的個數爲1。局部變量的個數,由編譯期決定。

max_locals的單位是Slot,Slot是虛擬機爲局部變量分配內存所使用的最小單位。對於長度不超過32位的數據類型,每一個局部變量佔用1個Slot。而double和long的數據類型長度爲64位,須要佔用兩個Slot。

code[]數組的字節數(code_length)

類型:u4
字節地址:000000FF~00000102
值:0x00000005

字節碼指令(code)

類型:u1
長度/字節數:5
字節地址:00000103~00000107

image

其中,第0、一、4字節爲字節碼指令,第二、3字節爲參數索引。

常量池

image

實例初始化方法字節碼指令信息

image

其中,初始化方法是沒有參數的,但args_size爲1。這實際上是由於對於非static方法,編譯器默認會將指向當前對象的this做爲方法的第一個參數,以便在調用方法的時候使用。

異常表長度(exception_table_length)

類型:u2
字節地址:00000108~00000109
值:0x0000

說明沒有異常表信息。

異常表(exception_table)

屬性計數器(attributes_count)

類型:u2
字節地址:0000010A~0000010B
值:0x0002

說明該字段有2個屬性。

第1個方法Code屬性的第1個屬性

名稱索引(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)

image

image

第1個方法Code屬性的第2個屬性

名稱索引(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)

image

start_pc和length二者結合起來就是這個局部變量在字節碼之中的做用域範圍。

也就是說,這個局部變量爲this,類型爲chapter6/TestClass,存放在局部變量表的第0個Slot,做用域爲code[0]~code[4]。

image

第1個方法對應的字節內容

image

第2個方法

訪問標誌(access_flags)

類型:u2
字節地址:0000012A~0000012B
值:0x0001

查表獲得對應的訪問標誌爲ACC_PUBLIC。

名稱索引(name_index)

類型:u2
字節地址:0000012C~0000012D
值:0x0010

對應常量池中的第16項常量,值爲inc,正是咱們定義的實例方法名。

描述符(descriptor_index)

類型:u2
字節地址:0000012E~0000012F
值:0x0011

對應常量池中的第17項常量,值爲()I,說明該方法無參數,返回類型爲int。

image

以上3項,說明該方法定義爲public int inc()。

屬性計數器(attributes_count)

類型:u2
字節地址:00000130~00000131
值:0x0001

說明該字段有1個屬性。

第1個屬性

名稱索引(attribute_name_index)

類型:u2
字節地址:00000132~00000133
值:0x0009

對應常量池中的第9項常量,值爲Code。

Code屬性值的長度(attribute_length)

類型:u4
字節地址:00000134~00000137
值:0x00000031

將0x00000031轉換爲十進制,計算獲得49。

Code操做數棧的最大深度(max_stack)

類型:u2
字節地址:00000138~00000139
值:0x0002

即最大深度爲2。

Code局部變量的個數(max_locals)

類型:u2
字節地址:0000013A~0000013B
值:0x0001

即局部變量的個數爲1。

code[]數組的字節數(code_length)

類型:u4
字節地址:0000013C~0000013F
值:0x00000007

Code字節碼指令(code)

類型:u1
長度/字節數:7
字節地址:00000140~00000146

image

其中,第0、一、四、五、6字節爲字節碼指令,第二、3字節爲參數索引。

常量池

image

實例初始化方法字節碼指令信息

image

Code異常表長度(exception_table_length)

類型:u2
字節地址:00000147~00000148
值:0x0000

說明沒有異常表信息。

Code異常表(exception_table)

Code屬性計數器(attributes_count)

類型:u2
字節地址:00000149~0000014A
值:0x0002

說明該字段有2個屬性。

第2個方法Code屬性的第1個屬性

名稱索引(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)

image

image

第2個方法Code屬性的第2個屬性

名稱索引(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)

image

start_pc和length二者結合起來就是這個局部變量在字節碼之中的做用域範圍。

也就是說,這個局部變量爲this,類型爲chapter6/TestClass,存放在局部變量表的第0個Slot,做用域爲code[0]~code[6]。

image

第2個方法對應的字節內容

image

類的屬性計數器(attributes_count)

類型:u2
字節地址:00000169~0000016A
值:0x0001

說明該類有1個屬性。

第1個屬性

名稱索引(attribute_name_index)

類型:u2
字節地址:0000016B~0000016C
值:0x0014

對應常量池中的第12項常量,值爲SourceFile,即class文件的Java源文件名稱。

屬性值的長度(attribute_length)

類型:u4
字節地址:0000016D~00000170
值:0x00000002

類的源文件名稱索引(sourcefile_index)

類型:u2
字節地址:00000171~00000172
值:0x0015

對應常量池中的第21項常量,值爲TestClass.java。

image

字節碼內容

image


參考

《Java虛擬機規範》(Java SE 8版)

《深刻理解Java虛擬機 JVM高級特性與最佳實踐》

我的公衆號

更多文章,請關注公衆號:二進制之路

二進制之路
相關文章
相關標籤/搜索