JVM_字節(jié)碼:字節(jié)碼相關(guān)概述

Java字節(jié)碼的整體結(jié)構(gòu):

整體結(jié)構(gòu)1.png

整體結(jié)構(gòu)2.png

整體結(jié)構(gòu)3.png

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)格定義好的。


字節(jié)碼的類(lèi)型.png

上面的表描述了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)1

表結(jié)構(gòu)2.png

方法表的集合:


表結(jié)構(gòu)1

表結(jié)構(gòu)2

方法表的屬性結(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ù)定義的屬性:


JVM規(guī)范預(yù)定義的屬性

方法中的每個(gè)屬性都是一個(gè)atrribute_info結(jié)構(gòu):


atrribute_info結(jié)構(gòu)

Code結(jié)構(gòu):
Code attribute的作用是保存該方法的結(jié)構(gòu),如所對(duì)應(yīng)的字節(jié)碼結(jié)構(gòu):


Code attribute對(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é)果:


image.png
-------
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)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,321評(píng)論 6 543
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,559評(píng)論 3 429
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 178,442評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 63,835評(píng)論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,581評(píng)論 6 412
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 55,922評(píng)論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,931評(píng)論 3 447
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 43,096評(píng)論 0 290
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,639評(píng)論 1 336
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,374評(píng)論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,591評(píng)論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,104評(píng)論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,789評(píng)論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 35,196評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 36,524評(píng)論 1 295
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,322評(píng)論 3 400
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,554評(píng)論 2 379

推薦閱讀更多精彩內(nèi)容