Java字節(jié)碼的整體結(jié)構(gòu):
Class字節(jié)碼中有兩種數(shù)據(jù)類(lèi)型:
字節(jié)碼數(shù)據(jù)直接量:這是基本的數(shù)據(jù)類(lèi)型,共細(xì)分為u1、u2、u4、u84種類(lèi)型,分別代表連續(xù)的1個(gè)字節(jié)、2個(gè)字節(jié)、4個(gè)字節(jié)、8個(gè)字節(jié)組成的整體數(shù)據(jù)。
表(數(shù)組):表是由多個(gè)基本數(shù)據(jù)或者其他表按照既定的順序組成的大的數(shù)據(jù)集合,表是有結(jié)構(gòu)的,它的結(jié)構(gòu)體現(xiàn)在:組成表的成分所在的位置和順序都是已經(jīng)嚴(yán)格定義好的。
上面的表描述了11種數(shù)據(jù)類(lèi)型的結(jié)構(gòu),其實(shí)在JDK1.7之后,又增加了3種,
(CONSTANT_MethodHandle_info、CONSTANT_MethodType_info以及CONSTANT_InvokeDynamic_info)這樣一共存在14種數(shù)據(jù)類(lèi)型。
Access_Flag訪問(wèn)標(biāo)志:
訪問(wèn)標(biāo)志信息包括Class文件是類(lèi)還是接口,是否被定義成public,是否是abstract,如果是類(lèi),是否被聲明為final。
修飾符的表:
Tips: 少了一個(gè)0x0002表示的是ACC_PRIVATE
0x0021: 是0x0001和0x0020的并集,表示的是ACC_PUBLIC和ACC_SUPER
00 21 // 表示的是ACCESS_FLAG 修飾符A&修飾符B&... ACC_PUBLIC(0x0001)&ACC_SUPER(0x0020)
00 03 // 當(dāng)前類(lèi)的全局限定名稱(chēng)指向常量池 #3 = Class #22 // com/compass/spring_lecture/binarycode/MyTest1
00 04 //表示當(dāng)前類(lèi)的父類(lèi)全局限定名稱(chēng)指向常量池 #4 = Class #23 // java/lang/Object
00 00 //表示接口的數(shù)量
00 01 //表示字段的數(shù)量 1
字段表的集合:
字段表用于描述類(lèi)和接口中聲明的變量,這里的字段包括類(lèi)級(jí)別的變量及實(shí)例變量,但是不包括方法內(nèi)部聲明的局部變量。
字段表結(jié)構(gòu):
方法表的集合:
方法表的屬性結(jié)構(gòu):
- JVM預(yù)定義了部分的attribute,但是編譯器自己也可以實(shí)現(xiàn)自己的attribute并寫(xiě)入到class文件中,供運(yùn)行時(shí)使用。
- 不同的attribute是通過(guò)attribute_name_index來(lái)區(qū)分的。
JVM規(guī)范預(yù)定義的屬性:
方法中的每個(gè)屬性都是一個(gè)atrribute_info結(jié)構(gòu):
Code結(jié)構(gòu):
Code attribute的作用是保存該方法的結(jié)構(gòu),如所對(duì)應(yīng)的字節(jié)碼結(jié)構(gòu):
Code結(jié)構(gòu):
- attribute_length表示attribute所包含的字節(jié)數(shù),不包含arribute_name_index和attribute_length字段。
- max_stack表示這個(gè)方法運(yùn)行的任何時(shí)刻所能達(dá)到的操作數(shù)棧的最大深度
- max_locals表示方法執(zhí)行期間創(chuàng)建的局部變量的數(shù)目,包含用來(lái)表示傳入的參數(shù)的局部變量
- code_length: 表示該方法所包含的字節(jié)碼的字節(jié)數(shù)以及具體的指令碼
- 具體字節(jié)碼即是該方法被調(diào)用時(shí),虛擬機(jī)所執(zhí)行的代碼
- exception_table,這里存放的是處理異常的信息
- 每個(gè)exception_table表項(xiàng)由start_pc、end_pc、handler_pc、catch_type組成
- start_pc和end_pc 表示在code數(shù)組中的從start_pc到end_pc處(包含start_pc不包含end_pc即([start_pc,end_pc)))的指令拋出異常會(huì)由這個(gè)表項(xiàng)來(lái)處理。
- handler_pc 表示處理異常的代碼的開(kāi)始處,catch_type表示會(huì)被處理的異常類(lèi)型,它指向常量池里的一個(gè)異常類(lèi)。當(dāng)catch_type為0時(shí),表示處理所有的異常。
完整的字節(jié)碼如下:
Classfile /C:/spring_lecture/target/classes/com/compass/spring_lecture/binarycode/MyTest1.class
Last modified 2019年6月26日; size 521 bytes
MD5 checksum e84ac7b4ed245fd5824849fb69bacc27
Compiled from "MyTest1.java"
public class com.compass.spring_lecture.binarycode.MyTest1
minor version: 0 //小版本
major version: 52 //大版本
flags: (0x0021) ACC_PUBLIC, ACC_SUPER
this_class: #3 // com/compass/spring_lecture/binarycode/MyTest1
super_class: #4 // java/lang/Object
interfaces: 0, fields: 1, methods: 3, attributes: 1
Constant pool://常量池
#1 = Methodref #4.#20 // java/lang/Object."<init>":()V
#2 = Fieldref #3.#21 // com/compass/spring_lecture/binarycode/MyTest1.a:I
#3 = Class #22 // com/compass/spring_lecture/binarycode/MyTest1
#4 = Class #23 // java/lang/Object
#5 = Utf8 a
#6 = Utf8 I
#7 = Utf8 <init>
#8 = Utf8 ()V
#9 = Utf8 Code
#10 = Utf8 LineNumberTable
#11 = Utf8 LocalVariableTable
#12 = Utf8 this
#13 = Utf8 Lcom/compass/spring_lecture/binarycode/MyTest1;
#14 = Utf8 getA
#15 = Utf8 ()I
#16 = Utf8 setA
#17 = Utf8 (I)V
#18 = Utf8 SourceFile
#19 = Utf8 MyTest1.java
#20 = NameAndType #7:#8 // "<init>":()V
#21 = NameAndType #5:#6 // a:I
#22 = Utf8 com/compass/spring_lecture/binarycode/MyTest1
#23 = Utf8 java/lang/Object
{
public com.compass.spring_lecture.binarycode.MyTest1();
descriptor: ()V
flags: (0x0001) ACC_PUBLIC
Code:
stack=2, locals=1, args_size=1
----------------------------------------------------------------
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: iconst_1
6: putfield #2 // Field a:I
9: return
----------------------------------------------------------------
LineNumberTable:
line 4: 0
line 6: 4
LocalVariableTable:
Start Length Slot Name Signature
0 10 0 this Lcom/compass/spring_lecture/binarycode/MyTest1;
public int getA();
descriptor: ()I
flags: (0x0001) ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
----------------------------------------------------------------
0: aload_0
1: getfield #2 // Field a:I
4: ireturn
LineNumberTable:
----------------------------------------------------------------
line 10: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/compass/spring_lecture/binarycode/MyTest1;
public void setA(int);
descriptor: (I)V
flags: (0x0001) ACC_PUBLIC
Code:
stack=2, locals=2, args_size=2
----------------------------------------------------------------
0: aload_0
1: iload_1
2: putfield #2 // Field a:I
5: return
----------------------------------------------------------------
LineNumberTable: //行號(hào)表
line 14: 0
line 15: 5
LocalVariableTable: //局部變量表
Start Length Slot Name Signature
0 6 0 this Lcom/compass/spring_lecture/binarycode/MyTest1;
0 6 1 a I
}
SourceFile: "MyTest1.java"
將常量池的字節(jié)碼抽取出來(lái)如下:
Constant pool://常量池
序號(hào) 類(lèi)型 引用
#1 = Methodref #4.#20 // java/lang/Object."<init>":()V
#2 = Fieldref #3.#21 // com/compass/spring_lecture/binarycode/MyTest1.a:I
#3 = Class #22 // com/compass/spring_lecture/binarycode/MyTest1
#4 = Class #23 // java/lang/Object
#5 = Utf8 a
#6 = Utf8 I
#7 = Utf8 <init>
#8 = Utf8 ()V
#9 = Utf8 Code
#10 = Utf8 LineNumberTable
#11 = Utf8 LocalVariableTable
#12 = Utf8 this
#13 = Utf8 Lcom/compass/spring_lecture/binarycode/MyTest1;
#14 = Utf8 getA
#15 = Utf8 ()I
#16 = Utf8 setA
#17 = Utf8 (I)V
#18 = Utf8 SourceFile
#19 = Utf8 MyTest1.java
#20 = NameAndType #7:#8 // "<init>":()V
#21 = NameAndType #5:#6 // a:I
#22 = Utf8 com/compass/spring_lecture/binarycode/MyTest1
#23 = Utf8 java/lang/Object
字節(jié)碼的16進(jìn)制信息:
ca fe ba be 00 00 00 34 00 18 0a 00 04 00 14 09
00 03 00 15 07 00 16 07 00 17 01 00 01 61 01 00
01 49 01 00 06 3c 69 6e 69 74 3e 01 00 03 28 29
56 01 00 04 43 6f 64 65 01 00 0f 4c 69 6e 65 4e
75 6d 62 65 72 54 61 62 6c 65 01 00 12 4c 6f 63
61 6c 56 61 72 69 61 62 6c 65 54 61 62 6c 65 01
00 04 74 68 69 73 01 00 2f 4c 63 6f 6d 2f 63 6f
6d 70 61 73 73 2f 73 70 72 69 6e 67 5f 6c 65 63
74 75 72 65 2f 62 69 6e 61 72 79 63 6f 64 65 2f
4d 79 54 65 73 74 31 3b 01 00 04 67 65 74 41 01
00 03 28 29 49 01 00 04 73 65 74 41 01 00 04 28
49 29 56 01 00 0a 53 6f 75 72 63 65 46 69 6c 65
01 00 0c 4d 79 54 65 73 74 31 2e 6a 61 76 61 0c
00 07 00 08 0c 00 05 00 06 01 00 2d 63 6f 6d 2f
63 6f 6d 70 61 73 73 2f 73 70 72 69 6e 67 5f 6c
65 63 74 75 72 65 2f 62 69 6e 61 72 79 63 6f 64
65 2f 4d 79 54 65 73 74 31 01 00 10 6a 61 76 61
2f 6c 61 6e 67 2f 4f 62 6a 65 63 74 00 21 00 03
00 04 00 00 00 01 00 02 00 05 00 06 00 00 00 03
00 01 00 07 00 08 00 01 00 09 00 00 00 38 00 02
00 01 00 00 00 0a 2a b7 00 01 2a 04 b5 00 02 b1
00 00 00 02 00 0a 00 00 00 0a 00 02 00 00 00 04
00 04 00 06 00 0b 00 00 00 0c 00 01 00 00 00 0a
00 0c 00 0d 00 00 00 01 00 0e 00 0f 00 01 00 09
00 00 00 2f 00 01 00 01 00 00 00 05 2a b4 00 02
ac 00 00 00 02 00 0a 00 00 00 06 00 01 00 00 00
0a 00 0b 00 00 00 0c 00 01 00 00 00 05 00 0c 00
0d 00 00 00 01 00 10 00 11 00 01 00 09 00 00 00
3e 00 02 00 02 00 00 00 06 2a 1b b5 00 02 b1 00
00 00 02 00 0a 00 00 00 0a 00 02 00 00 00 0e 00
05 00 0f 00 0b 00 00 00 16 00 02 00 00 00 06 00
0c 00 0d 00 00 00 00 00 06 00 05 00 06 00 01 00
01 00 12 00 00 00 02 00 13
對(duì)上述的16進(jìn)制編碼進(jìn)行分析:
ca fe ba be //魔數(shù)
00 00 00 34 //版本信息 00 00 (次版本號(hào)) 00 34(52主版本號(hào))
00 18 //CONSTANT_POOL START 常量池?cái)?shù)量信息 00 16 (24)
0a 00 04 00 14 09 00 03 00 15 07 00 16 07 00
17 01 00 01 61 01 00 01 49 01 00 06 3c 69 6e
69 74 3e 01 00 03 28 29 56 01 00 04 43 6f 64
65 01 00 0f 4c 69 6e 65 4e 75 6d 62 65 72 54
61 62 6c 65 01 00 12 4c 6f 63 61 6c 56 61 72
69 61 62 6c 65 54 61 62 6c 65 01 00 04 74 68
69 73 01 00 2f 4c 63 6f 6d 2f 63 6f 6d 70 61
73 73 2f 73 70 72 69 6e 67 5f 6c 65 63 74 75
72 65 2f 62 69 6e 61 72 79 63 6f 64 65 2f 4d
79 54 65 73 74 31 3b 01 00 04 67 65 74 41 01
00 03 28 29 49 01 00 04 73 65 74 41 01 00 04 28
49 29 56 01 00 0a 53 6f 75 72 63 65 46 69 6c 65
01 00 0c 4d 79 54 65 73 74 31 2e 6a 61 76 61 0c
00 07 00 08 0c 00 05 00 06 01 00 2d 63 6f 6d 2f
63 6f 6d 70 61 73 73 2f 73 70 72 69 6e 67 5f 6c
65 63 74 75 72 65 2f 62 69 6e 61 72 79 63 6f 64
65 2f 4d 79 54 65 73 74 31 01 00 10 6a 61 76 61
2f 6c 61 6e 67 2f 4f 62 6a 65 63 74 //CONSTANT_POOL END
00 21 // 表示的是ACCESS_FLAG 修飾符A&修飾符B&... ACC_PUBLIC(0x0001)&ACC_SUPER(0x0020)
00 03 // 當(dāng)前類(lèi)的全局限定名稱(chēng)指向常量池 #3 = Class #22 //
com/compass/spring_lecture/binarycode/MyTest1
00 04 //表示當(dāng)前類(lèi)的父類(lèi)全局限定名稱(chēng)指向常量池 #4 = Class #23 // java/lang/Object
00 00 //表示接口的數(shù)量
00 01 //表示字段的數(shù)量 1
00 02 //字段的描述符ACCESS_FLAG ACC_PRIVATE(0x0002)
00 05 //5 表示字段的名稱(chēng) #5 = Utf8 a
00 06 //6 表示字段的描述符也就是類(lèi)型 #6 = Utf8 I
00 00 //字段的屬性個(gè)數(shù)0
00 03 //表示方法的數(shù)量 3
00 01 //方法的訪問(wèn)標(biāo)記 ACC_PUBLIC(0x0001)
00 07 //方法名字索引 #7 = Utf8 <init>
00 08 //方法的描述符索引 #8 = Utf8 ()V
00 01 //方法中屬性的個(gè)數(shù) 1 方法的屬性是this args_size=1
00 09 //表示的是屬性名的索引 #9 = Utf8 Code(表示代碼片段 方法的執(zhí)行代碼)
00 00 00 38 //U4 表示屬性的長(zhǎng)度 38=16*3+8=48+8=56 表示attribute所包含的字節(jié)數(shù),不包含arribute_name_index和attribute_length字段
00 02 //U2 表示 max_stack stack=2 表示這個(gè)方法運(yùn)行的任何時(shí)刻所能達(dá)到的操作數(shù)棧的最大深度
00 01 //U2 表示 max_local locals=1 表示方法執(zhí)行期間創(chuàng)建的局部變量的數(shù)目,包含用來(lái)表示傳入的參數(shù)的局部變量
00 00 00 0a //表示的是code_length 10 //表示該方法所包含的字節(jié)碼的字節(jié)數(shù)以及具體的指令碼 具體字節(jié)碼即是該方法被調(diào)用時(shí),虛擬機(jī)所執(zhí)行的代碼
第6章 . JVM的機(jī)器執(zhí)行指令集:
Chapter 6. The Java Virtual Machine Instruction Set :https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html
2a b7 00 01 2a 04 b5 00 02 b1 //這10個(gè)字節(jié)對(duì)應(yīng)方法的執(zhí)行代碼 這里需要參考JVM的規(guī)范:
---
2a ---aload_0 = 42 (0x2a)
Description:
The <n> must be an index into the local variable array of the current frame (§2.6).
The local variable at <n> must contain a reference. The objectref in the local
variable at <n> is pushed onto the operand stack.
-------
b7 ---invokespecial = 183 (0xb7)
b7后面的2個(gè)字節(jié)
00 01 ---表示它接收的參數(shù)
Description:
調(diào)用了父類(lèi)的構(gòu)造器,詳細(xì)信息見(jiàn)規(guī)范比較多
-------
2a ---aload_0 = 42 (0x2a)
Description:
The <n> must be an index into the local variable array of the current frame (§2.6).
The local variable at <n> must contain a reference. The objectref in the local
variable at <n> is pushed onto the operand stack.
-------
04 ---iconst_1 = 4 (0x4)
Description:
Push the int constant <i> (-1, 0, 1, 2, 3, 4 or 5) onto the operand stack.
-------
b5 ---putfield = 181 (0xb5)
Description:
給成員變量賦值
The unsigned indexbyte1 and indexbyte2 are used to construct an index into the run-time constant pool of the current class (§2.6), where the value of the index is (indexbyte1 << 8) | indexbyte2. The run-time constant pool item at that index must be a symbolic reference to a field (§5.1), which gives the name and descriptor of the field as well as a symbolic reference to the class in which the field is to be found. The class of objectref must not be an array. If the field is protected, and it is a member of a superclass of the current class, and the field is not declared in the same run-time package (§5.3) as the current class, then the class of objectref must be either the current class or a subclass of the current class.
The referenced field is resolved (§5.4.3.2). The type of a value stored by a putfield instruction must be compatible with the descriptor of the referenced field (§4.3.2). If the field descriptor type is boolean, byte, char, short, or int, then the value must be an int. If the field descriptor type is float, long, or double, then the value must be a float, long, or double, respectively. If the field descriptor type is a reference type, then the value must be of a type that is assignment compatible (JLS §5.2) with the field descriptor type. If the field is final, it must be declared in the current class, and the instruction must occur in an instance initialization method (<init>) of the current class (§2.9).
The value and objectref are popped from the operand stack. The objectref must be of type reference. The value undergoes value set conversion (§2.8.3), resulting in value', and the referenced field in objectref is set to value'.
-------
00 02 --- 表示putfield的參數(shù)
Description:
#2 = Fieldref #3.#21 // com/compass/spring_lecture/binarycode/MyTest1.a:I
-------
b1 --- return = 177 (0xb1)
Description:
The current method must have return type void. If the current method is a synchronized method, the monitor entered or reentered on invocation of the method is updated and possibly exited as if by execution of a monitorexit instruction (§monitorexit) in the current thread. If no exception is thrown, any values on the operand stack of the current frame (§2.6) are discarded.
The interpreter then returns control to the invoker of the method, reinstating the frame of the invoker.
-------
00 00 //表示這個(gè)方法的異常表
00 02 //表示這個(gè)方法存在2個(gè)屬性(不是成員變量的概念 不要混淆)
附加屬性:
- 接下來(lái)就是方法的附加屬性
-
LineNumberTable: 這個(gè)屬性用來(lái)表示code數(shù)組中的字節(jié)碼和Java代碼行數(shù)之間的關(guān)系。這個(gè)屬性可以用來(lái)在調(diào)試的時(shí)候定位代碼執(zhí)行的行數(shù)。
LineNumberTable的結(jié)構(gòu)
00 0a //10---#10 = Utf8 LineNumberTable 行號(hào)表
00 00 00 0a //10 行號(hào)表屬性的長(zhǎng)度
00 02 00 00 00 04 00 04 00 06 //行號(hào)信息
00 02: 表示存在幾對(duì)映射(10-2)/2=4 4個(gè)字節(jié)一個(gè)映射關(guān)系
00 00 00 04:字節(jié)碼的偏移量0映射的行號(hào)為4
00 04 00 06:字節(jié)碼的偏移量4映射的行號(hào)為6
可以對(duì)照jclasslib的結(jié)果來(lái)驗(yàn)證自己的分析結(jié)果:
-------
00 0b //表示局部變量表 11
00 00 00 0c //表示局部變量表的長(zhǎng)度 12
00 01 //局部變量的個(gè)數(shù) 1
00 00 //表示局部變量的開(kāi)始位置
00 0a //表示局部變量的結(jié)束位置
00 //索引是0
0c //對(duì)應(yīng)常量池的位置 12 #12 = Utf8 this 是編譯器默認(rèn)作為方法的第1個(gè)參數(shù)傳進(jìn)來(lái) ---成員方法
00 0d // 當(dāng)前對(duì)象的描述符 #13 = Utf8 Lcom/compass/spring_lecture/binarycode/MyTest1;
00 00 // jdk 1.6 之后的javac 提供了StackMapTable 屬性長(zhǎng)度是1 用于校驗(yàn)
-------
00 01 //方法的訪問(wèn)標(biāo)記 ACC_PUBLIC(0x0001)
00 0e //方法的名字索引 #14 = Utf8 getA
00 0f //方法的描述符索引 #15 = Utf8 ()I
00 01 //方法中屬性的個(gè)數(shù) 1 方法的屬性是this args_size=1
00 09 //表示的是屬性名的索引 #9 = Utf8 Code(表示代碼片段 方法的執(zhí)行代碼)
00 00 00 2f //U4 表示屬性的長(zhǎng)度 2f=16*2+15=47 表示attribute所包含的字節(jié)數(shù),不包含arribute_name_index和attribute_length字段
00 01 //U2 表示 max_stack stack=1 表示這個(gè)方法運(yùn)行的任何時(shí)刻所能達(dá)到的操作數(shù)棧的最大深度
00 01 //U2 表示 max_local locals=1 表示方法執(zhí)行期間創(chuàng)建的局部變量的數(shù)目,包含用來(lái)表示傳入的參數(shù)的局部變量
00 00 00 05 //U4 表示的是code_length 5 //表示該方法所包含的字節(jié)碼的字節(jié)數(shù)以及具體的指令碼 具體字節(jié)碼即是該方法被調(diào)用時(shí),虛擬機(jī)所執(zhí)行的代碼
-------
2a b4 00 02 ac //參考JVM Introductuion Set Specification
0 aload_0(0x2a)
1 getfield(0xb4) #2(0x 00 02) <com/compass/spring_lecture/binarycode/MyTest1.a>
4 ireturn(0xac)
00 00 //表示這個(gè)方法的異常表
00 02 //表示這個(gè)方法存在2個(gè)屬性(不是成員變量的概念 不要混淆)
00 0a //10---#10 = Utf8 LineNumberTable 行號(hào)表
00 00 00 06 //6 行號(hào)表屬性的長(zhǎng)度
00 01 //表示存在幾對(duì)映射(6-2)/1=4 表示4個(gè)字節(jié)一個(gè)映射
00 00 00 0a // 字節(jié)碼的偏移量映射0的行號(hào)為12
00 0b //表示局部變量表 11
00 00 00 0c //表示局部變量表的長(zhǎng)度 12
00 01 //局部變量的個(gè)數(shù) 1
00 00 //表示局部變量的開(kāi)始位置
00 05 //表示局部變量的結(jié)束位置
00 //索引是0
0c //對(duì)應(yīng)常量池的位置 12 #12 = Utf8 this 是編譯器默認(rèn)作為方法的第1個(gè)參數(shù)傳進(jìn)來(lái) ---成員方法
00 0d // 當(dāng)前對(duì)象的描述 #13 = Utf8 Lcom/compass/spring_lecture/binarycode/MyTest1;
00 00 // jdk 1.6 之后的javac 提供了StackMapTable 屬性長(zhǎng)度是1 用于校驗(yàn)
-------
00 01 //方法的訪問(wèn)標(biāo)記 ACC_PUBLIC(0x0001)
00 10 //#16 = Utf8 setA
00 11 //#17 = Utf8 (I)V
00 01 //方法中屬性的個(gè)數(shù) 1 方法的屬性是this args_size=1
00 09 //表示的是屬性名的索引 #9 = Utf8 Code(表示代碼片段 方法的執(zhí)行代碼)
00 00 00 3e//U4 表示屬性的長(zhǎng)度 3e=16*3+14=48+14=62 表示attribute所包含的字節(jié)數(shù),不包含arribute_name_index和attribute_length字段
00 02 //U2 表示 max_stack stack=1 表示這個(gè)方法運(yùn)行的任何時(shí)刻所能達(dá)到的操作數(shù)棧的最大深度
00 02 //U2 表示 max_stack stack=1 表示這個(gè)方法運(yùn)行的任何時(shí)刻所能達(dá)到的操作數(shù)棧的最大深度
00 00 00 06 //U4 表示的是code_length 6 //表示該方法所包含的字節(jié)碼的字節(jié)數(shù)以及具體的指令碼 具體字節(jié)碼即是該方法被調(diào)用時(shí),虛擬機(jī)所執(zhí)行的代碼
2a 1b b5 00 02 b1
0 aload_0(0x2a)
1 iload_1(0x1b)
2 putfield (0xb5)#2(0x0002) <com/compass/spring_lecture/binarycode/MyTest1.a>
5 return(0xb1)
00 00 //表示這個(gè)方法的異常表
00 02 //表示這個(gè)方法存在2個(gè)屬性(不是成員變量的概念 不要混淆)
00 0a //10---#10 = Utf8 LineNumberTable 行號(hào)表
00 00 00 0a //10 行號(hào)表屬性的長(zhǎng)度
00 02//表示存在幾對(duì)映射(10-2)/1=4 表示4個(gè)字節(jié)一個(gè)映射
00 00 00 0e//字節(jié)碼的偏移量映射0的行號(hào)為14
00 05 00 0f //字節(jié)碼的偏移量映射5的行號(hào)為15
00 0b////表示局部變量表 11
00 00 00 16//表示局部變量表的長(zhǎng)度 22
----------------
00 02 //局部變量的個(gè)數(shù) 2
00 00 //表示局部變量的開(kāi)始位置
00 06 //表示局部變量的結(jié)束位置
00 //索引是0
0c //對(duì)應(yīng)常量池的位置 12 #12 = Utf8 this 是編譯器默認(rèn)作為方法的第1個(gè)參數(shù)傳進(jìn)來(lái) ---成員方法
00 0d // 當(dāng)前對(duì)象的描述符 #13 = Utf8 Lcom/compass/spring_lecture/binarycode/MyTest1;
00 00 //jdk 1.6 之后的javac 提供了StackMapTable 屬性長(zhǎng)度是1 用于校驗(yàn)
00 00 //起始位置是0
00 06 //結(jié)束位置是6
00 //索引是0
05 //#5 = Utf8 a
00 06 // #6 = Utf8 I
00 01 //jdk 1.6 之后的javac 提供了StackMapTable 屬性長(zhǎng)度是1 用于校驗(yàn)
屬性?xún)?nèi)容
00 01//一個(gè)屬性
00 12//對(duì)應(yīng)常量池的18 #18 = Utf8 SourceFile
00 00 00 02//長(zhǎng)度是2 后面的兩個(gè)字節(jié)
00 13//對(duì)應(yīng)源文件
附加屬性
- 接下來(lái)就是方法的附加屬性
-
LineNumberTable: 這個(gè)屬性用來(lái)表示code數(shù)組中的字節(jié)碼和Java代碼行數(shù)之間的關(guān)系。這個(gè)屬性可以用來(lái)在調(diào)試的時(shí)候定位代碼執(zhí)行的行數(shù)。
LineNumberTable的結(jié)構(gòu)