Java虛擬機-Class文件結(jié)構(gòu)之方法表

1 解析示例

示例源碼

public class ClassStructureMethod {
    public  void greeting() throws Exception {
       try {
           int a=1;
           int b=1;
           int c=a+b;
           System.out.println(c);
       }catch (Exception e){
           System.out.println("catch");
       }finally {
           System.out.println("finally");
       }
    }
}

示例常量池

Constant pool:
   #1 = Methodref          #9.#30         // java/lang/Object."<init>":()V
   #2 = Fieldref           #31.#32        // java/lang/System.out:Ljava/io/PrintStream;
   #3 = Methodref          #33.#34        // java/io/PrintStream.println:(I)V
   #4 = String             #35            // finally
   #5 = Methodref          #33.#36        // java/io/PrintStream.println:(Ljava/lang/String;)V
   #6 = Class              #37            // java/lang/Exception
   #7 = String             #38            // catch
   #8 = Class              #39            // jvm/ClassStructureMethod
   #9 = Class              #40            // java/lang/Object
  #10 = Utf8               <init>
  #11 = Utf8               ()V
  #12 = Utf8               Code
  #13 = Utf8               LineNumberTable
  #14 = Utf8               LocalVariableTable
  #15 = Utf8               this
  #16 = Utf8               Ljvm/ClassStructureMethod;
  #17 = Utf8               greeting
  #18 = Utf8               a
  #19 = Utf8               I
  #20 = Utf8               b
  #21 = Utf8               c
  #22 = Utf8               e
  #23 = Utf8               Ljava/lang/Exception;
  #24 = Utf8               StackMapTable
  #25 = Class              #37            // java/lang/Exception
  #26 = Class              #41            // java/lang/Throwable
  #27 = Utf8               Exceptions
  #28 = Utf8               SourceFile
  #29 = Utf8               ClassStructureMethod.java
  #30 = NameAndType        #10:#11        // "<init>":()V
  #31 = Class              #42            // java/lang/System
  #32 = NameAndType        #43:#44        // out:Ljava/io/PrintStream;
  #33 = Class              #45            // java/io/PrintStream
  #34 = NameAndType        #46:#47        // println:(I)V
  #35 = Utf8               finally
  #36 = NameAndType        #46:#48        // println:(Ljava/lang/String;)V
  #37 = Utf8               java/lang/Exception
  #38 = Utf8               catch
  #39 = Utf8               jvm/ClassStructureMethod
  #40 = Utf8               java/lang/Object
  #41 = Utf8               java/lang/Throwable
  #42 = Utf8               java/lang/System
  #43 = Utf8               out
  #44 = Utf8               Ljava/io/PrintStream;
  #45 = Utf8               java/io/PrintStream
  #46 = Utf8               println
  #47 = Utf8               (I)V
  #48 = Utf8               (Ljava/lang/String;)V

2 方法表前置結(jié)構(gòu)

image
  • 類訪問標(biāo)志2個字節(jié)(u2)來描述阱当,對應(yīng)16進制0x0021俏扩,對照J(rèn)ava虛擬機規(guī)范定義,匹配ACC_PUBLIC弊添、ACC_SUPER录淡,表示當(dāng)前類的修飾符為public。

  • 類名用2位字節(jié)(u2)來描述,對應(yīng)16進制0x0008油坝,即十進制的8嫉戚,8是常量池數(shù)組的一個下標(biāo),指向常量池中一個常量澈圈,通過對照javap中結(jié)果中對應(yīng)到一個CONSTANT_Class_info類型的常量(下標(biāo)#8),CONSTANT_Class_info類型常量其值轉(zhuǎn)換為整數(shù)20彬檀,指向常量池中一個常量,通過對照javap中結(jié)果中對應(yīng)到一個CONSTANT_Utf8_info類型的常量(下標(biāo)#39)瞬女,字符串值為"jvm/ClassStructureMethod"窍帝。

  • 父類名用2位字節(jié)(u2)來描述,對應(yīng)16進制0x0009,即十進制的9诽偷,9是常量池數(shù)組的一個下標(biāo)坤学,指向常量池中一個常量,通過對照javap中結(jié)果中對應(yīng)到一個CONSTANT_Class_info類型的常量(下標(biāo)#9),CONSTANT_Class_info類型常量其值轉(zhuǎn)換為整數(shù)21报慕,指向常量池中一個常量拥峦,通過對照javap中結(jié)果中對應(yīng)到一個CONSTANT_Utf8_info類型的常量(下標(biāo)#40),字符串值為"java/lang/Object"卖子。

  • 類接口數(shù)量用2位字節(jié)(u2)來描述,對應(yīng)16進制0x0000,即十進制的0刑峡,表示當(dāng)前類沒有實現(xiàn)接口洋闽。因此Class文件中不存在接口名稱描述。

  • 字段數(shù)量用2位字節(jié)(u2)來描述,對應(yīng)16進制0x0000突梦,即十進制的0诫舅,表示當(dāng)前類沒有字段。因此Class文件中不存在字段的描述宫患。

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

方法表集合的結(jié)構(gòu)

方法表集合的結(jié)構(gòu)被劃分為方法表數(shù)量方法表集合刊懈。

方法表數(shù)量(methods_count):表示類中定義的方法個數(shù),其中除了自定義的方法外娃闲,每一個類中都會存在名稱為"<init>"構(gòu)造函數(shù)虚汛,如果類中定義靜態(tài)變量或者靜態(tài)塊,則還會存在一個名稱為"<clinit>"類初始化方法皇帮。

方法表(method_info):表示類中定義某一個方法卷哩。其中涵蓋了方法的所有信息。

image

3 方法表數(shù)量(methods_count)

Java虛擬機規(guī)范中方法表數(shù)量用2個字節(jié)(u2)用來表示属拾。

示例中方法表數(shù)量

示例中方法數(shù)量将谊,對應(yīng)16進制0x0002冷溶,即十進制的2,代表Class文件中有2個方法尊浓。

image

對比源代碼中ClassStructureMethod類定義逞频,存在一個構(gòu)造方法<init>和自定義方法greeting(),共兩個方法栋齿。

public class ClassStructureMethod {
    public  void greeting() throws Exception {
       try {
           int a=1;
           int b=1;
           int c=a+b;
           System.out.println(c);
       }catch (Exception e){
           System.out.println("catch");
       }finally {
           System.out.println("finally");
       }
    }
}

Class文件中init方法的描述

本章節(jié)主要用來解析greeting方法在Class文件中的結(jié)構(gòu)苗胀,在此跳過<init>方法部分描述。

Class文件中init方法的描述

image

4 方法表(methods_info)

Java虛擬機規(guī)范定義方法表結(jié)構(gòu)

image
  • 方法訪問標(biāo)志(access_flags)
  • 方法名稱索引(name_index)
  • 方法描述符索引(descriptor_index)
  • 方法屬性表集合(attributes)
4.1 方法訪問標(biāo)志(access_flags)

Java虛擬機規(guī)范中方法訪問標(biāo)志用2個字節(jié)(u2)用來表示褒颈。

Java虛擬機規(guī)范定義方法訪問標(biāo)志

image

示例中方法訪問標(biāo)志

字段修飾符用2個字節(jié)(u2)來描述柒巫,對應(yīng)16進制0x0001,對照J(rèn)VM規(guī)范表中方法方法訪問標(biāo)志為ACC_PUBLIC,表示方法被"public"修飾

image

對比源代碼中可以發(fā)現(xiàn)greeting方法的修飾符為"public"相匹配

public class ClassStructureMethod {
    public  void greeting() throws Exception {
       try {
           int a=1;
           int b=1;
           int c=a+b;
           System.out.println(c);
       }catch (Exception e){
           System.out.println("catch");
       }finally {
           System.out.println("finally");
       }
    }
}
4.2 方法名稱(name_index)

Java虛擬機規(guī)范中方法名稱用2個字節(jié)(u2)用來表示谷丸”ぬ停可以換算成為一個整數(shù),這個整數(shù)是常量池數(shù)組的一個下標(biāo)刨疼,指向中一個CONSTANT_Utf8_info類型的常量用來描述方法的名稱泉唁。

示例方法名稱

方法名用2位字節(jié)(u2)來描述,對應(yīng)16進制0x0011,即十進制的17揩慕,17是常量池數(shù)組的一個下標(biāo)亭畜,指向常量池中一個常量,通過對照javap中結(jié)果中對應(yīng)到一個CONSTANT_Utf8_info類型的常量(下標(biāo)#17)迎卤,對應(yīng)字符串"greeting",表示方法名稱

image
4.3 方法描述符(descriptor_index)

按照J(rèn)ava虛擬機規(guī)范方法描述符用2位字節(jié)(u2)來描述拴鸵,可以換算成為一個整數(shù),這個整數(shù)是常量池數(shù)組的一個下標(biāo)蜗搔,指向中一個CONSTANT_Utf8_info類型的常量用來描述方法描述符劲藐。

關(guān)于方法的描述符在常量池中講過主要用來描述方法的參數(shù)和返回類型。

示例中方法描述符

方法修飾符用2個字節(jié)(u2)描述,對應(yīng)16進制0x000B樟凄,即十進制的11聘芜,11是常量池數(shù)組的一個下標(biāo),指向常量池中一個常量缝龄,通過對照javap中結(jié)果中對應(yīng)到一個CONSTANT_Utf8_info類型的常量(下標(biāo)#11)汰现,對應(yīng)字符串"()V",表示greeting方法不需要傳遞參數(shù),且不需要返回值

image

4.4 方法中的屬性

4.4.1 屬性表

屬性表(attribute_info)作用于Class文件叔壤、字段表瞎饲、方法表。它們都可以攜帶自己的屬性集合炼绘,用于描述某些場景專有的信息企软。

4.4.2 虛擬機規(guī)范中定義屬性表類型
image
4.4.3 屬性表集合的結(jié)構(gòu)

屬性表集合的結(jié)構(gòu)被劃分為屬性表數(shù)量屬性表集合。

屬性表數(shù)量(methods_count):表示方法中定義的屬性個數(shù)饭望。

屬性表(method_info):表示方法中定義某一個屬性仗哨。其中涵蓋了屬性的所有信息形庭。

4.4.4 用于方法中屬性表

對于方法來說常用到的屬性有如下幾種:"code","Exception","Deprecated","Synthetic"。

  • code:用來表示方法中java字節(jié)碼

  • Exception:用來記錄方法中的異常信息厌漂。

  • Deprecated:用來表示方法是否被@Deprecated修飾

  • Synthetic:表示方法是否被編譯器自動生成萨醒。

4.4.5 屬性表通用格式

屬性名稱索引:屬性名稱索引占用2個字節(jié),可以換算成為一個整數(shù)苇倡,這個整數(shù)是常量池數(shù)組的一個下標(biāo)富纸,指向中一個CONSTANT_Utf8_info類型的常量用來描述屬性名稱。通過屬性名稱就可以確定屬性表類型

屬性長度:占用4個字節(jié)旨椒,它的值表示緊跟其后的多少個字節(jié)是拿來表示這個屬性信息的晓褪。

屬性值:由若個個字節(jié)構(gòu)造,字節(jié)的大小取決屬性的長度

image

4.5 屬性表數(shù)量

Java虛擬機規(guī)范中屬性表數(shù)量用2個字節(jié)(u2)用來表示综慎。

示例中屬性表數(shù)量

示例中屬性表涣仿,對應(yīng)16進制0x0002,即十進制的2示惊,代表方法中有2個屬性好港。

image

4.6 屬性表

4.6.1 Code屬性
4.6.1.1 Code屬性名稱索引

屬性名稱索引用2個字節(jié)(u2)描述,對應(yīng)16進制0x000C,即十進制的12米罚,12是常量池數(shù)組的一個下標(biāo)钧汹,指向常量池中一個常量,通過對照javap中結(jié)果中對應(yīng)到一個CONSTANT_Utf8_info類型的常量(下標(biāo)#12)录择,對應(yīng)字符串"code",表示當(dāng)前屬性code類型的屬性拔莱。

image
4.6.1.2 Code屬性結(jié)構(gòu)

通過屬性名稱索引知道了方法的第一個索引名稱為"code".其虛擬機規(guī)范中的定義如下:

image
  • attribute_name_index,屬性名稱索引,占有2個字節(jié)隘竭,其內(nèi)的值指向了常量池中的某一項辨宠,該項表示字符串“Code”;
  • attribute_length,屬性長度,占有 4個字節(jié)货裹,其內(nèi)的值表示后面有多少個字節(jié)是屬于此Code屬性表的;
  • max_stack,操作數(shù)棧深度的最大值精偿,占有 2 個字節(jié)弧圆,在方法執(zhí)行的任意時刻,操作數(shù)棧都不應(yīng)該超過這個值笔咽,虛擬機的運行的時候搔预,會根據(jù)這個值來設(shè)置該方法對應(yīng)的棧幀(Stack Frame)中的操作數(shù)棧的深度;
  • max_locals,最大局部變量數(shù)目叶组,占有 2個字節(jié)拯田,其內(nèi)的值表示局部變量表所需要的存儲空間大小甩十;
  • code_length,Java字節(jié)碼的長度船庇,占有 4 個字節(jié)吭产,表示跟在其后的多少個字節(jié)表示的是機器指令;
  • code,Java字節(jié)碼鸭轮,該區(qū)域占有的字節(jié)數(shù)目由 code_length中的值決定臣淤。JVM最底層的要執(zhí)行的Java字節(jié)碼指令就存儲在這里;
  • exception_table_length,顯式異常表長度窃爷,占有2個字節(jié)邑蒋,如果在方法代碼中出現(xiàn)了try{} catch()形式的結(jié)構(gòu),該值不會為空按厘,緊跟其后會跟著若干個exception_table結(jié)構(gòu)體医吊,以表示異常捕獲情況;
  • exception_table逮京,顯式異常表卿堂,占有8 個字節(jié),start_pc,end_pc,handler_pc中的值都表示的是PC計數(shù)器中的指令地址造虏。exception_table表示的意思是:如果字節(jié)碼從第start_pc行到第end_pc行之間出現(xiàn)了catch_type所描述的異常類型御吞,那么將跳轉(zhuǎn)到handler_pc行繼續(xù)處理。
  • attribute_count,屬性計數(shù)器漓藕,占有 2 個字節(jié)陶珠,表示Code屬性表的其他屬性的數(shù)目
  • attribute_info,表示Code屬性表具有的屬性表,它主要分為兩個類型的屬性表:“LineNumberTable”類型和“LocalVariableTable”類型享钞。
  • “LineNumberTable”類型的屬性表記錄著Java源碼和機器指令之間的對應(yīng)關(guān)系
  • “LocalVariableTable”類型的屬性表記錄著局部變量描述
4.6.1.3 Code屬性長度

屬性長度索引用4個字節(jié)(u4)描述,對應(yīng)16進制0x000000EB揍诽,即十進制的235,表示屬性的長度占用235個字節(jié)

image
4.6.1.4 Code屬性max_stack

操作數(shù)棧深度的最大值用2個字節(jié)(u2)描述,對應(yīng)16進制0x002,即十進制的2,表示方法中操作數(shù)棧深度最大值為2

image
4.6.1.5 Code屬性max_locals

最大局部變量數(shù)目用2個字節(jié)(u2)描述,對應(yīng)16進制0x005栗竖,即十進制的5,表示最大局部變量數(shù)目為5

image
4.6.1.6 Code屬性code_length

java字節(jié)碼的長度用4個字節(jié)(u4)描述,對應(yīng)16進制0x0000003C暑脆,即十進制的60,表示ava字節(jié)碼的長度為60

image
4.6.1.7 Code屬性code

java字節(jié)碼的長度用60個字節(jié)描述

image
4.6.1.8 Code屬性中異常表集合

異常表集合的結(jié)構(gòu)被劃分為異常表數(shù)量異常表集合。

異常表數(shù)量(exceptions_count):表示方法代碼中可能存在拋出異常個數(shù)狐肢。

異常表(exception_info):表示代碼中一個異常添吗。

4.6.1.8.1 Code屬性中異常表數(shù)量

Code屬性中異常表數(shù)量用2個字節(jié)(u2)描述,對應(yīng)16進制0x004,即十進制的4,表示異常表數(shù)量為4

image
4.6.1.8.2 Code屬性中異常表結(jié)構(gòu)

異常表用來表示的意思是:如果字節(jié)碼從第start_pc行到第end_pc行之間出現(xiàn)了catch_type所描述的異常類型份名,那么將跳轉(zhuǎn)到handler_pc行繼續(xù)處理碟联。

名稱 字節(jié)長度 含義
start_pc 2個字節(jié) 異常發(fā)生起始字節(jié)指令行
end_pc 2個字節(jié) 異常發(fā)生結(jié)束字節(jié)指令行
handler_pc 2個字節(jié) 異常處理字節(jié)指令行
catch_type 2個字節(jié) 異常類型
  • 異常發(fā)生起始字節(jié)指令行用2個字節(jié)(u2)描述,對應(yīng)16進制0x0000,即十進制的0,表示異常發(fā)生起始字節(jié)指令行為0

  • 異常發(fā)生結(jié)束字節(jié)指令行用2個字節(jié)(u2)描述,對應(yīng)16進制0x000f僵腺,即十進制的15,表示異常發(fā)生結(jié)束字節(jié)指令行為15

  • 異常處理字節(jié)指令行用2個字節(jié)(u2)描述,對應(yīng)16進制0x001A鲤孵,即十進制的26,表示異常處理字節(jié)指令行為26

  • 異常類型用2個字節(jié)(u2)描述,對應(yīng)16進制0x0006,即十進制的6,6是常量池數(shù)組的一個下標(biāo)辰如,指向常量池中一個常量普监,通過對照javap中結(jié)果中對應(yīng)到一個CONSTANT_Utf8_info類型的常量(下標(biāo)#6),對應(yīng)字符串"java/lang/Exception"

image

這里同樣可以使用javap反編譯工具來解析獲取。我們在此比對下凯正,需要注意的是這里行表示的是反編譯工具中字節(jié)指令的行而非源代碼中的行毙玻。

       stack=2, locals=5, args_size=1
         0: iconst_1
         1: istore_1
         2: iconst_1
         3: istore_2
         4: iload_1
         5: iload_2
         6: iadd
         7: istore_3
         8: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
        11: iload_3
        12: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
        15: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
        18: ldc           #4                  // String finally
        20: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        23: goto          59
        26: astore_1
        27: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
        30: ldc           #7                  // String catch
        32: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        35: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
        38: ldc           #4                  // String finally
        40: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        43: goto          59
        46: astore        4
        48: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
        51: ldc           #4                  // String finally
        53: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        56: aload         4
        58: athrow
        59: return
      Exception table:
         from    to  target type
             0    15    26   Class java/lang/Exception
             0    15    46   any
            26    35    46   any
            46    48    46   any

對比源代碼

public class ClassStructureMethod {
    public  void greeting() throws Exception {
       try {
           int a=1;
           int b=1;
           int c=a+b;
           System.out.println(c);
       }catch (Exception e){
           System.out.println("catch");
       }finally {
           System.out.println("finally");
       }
    }
}

code屬性其他異常如下

image
4.6.1.9 Code屬性中的屬性

code屬性內(nèi)部同樣有屬性集合

屬性表集合的結(jié)構(gòu)同樣被劃分為屬性表數(shù)量和屬性表集合。

屬性表數(shù)量(methods_count):表示方法中定義的屬性個數(shù)漆际。

屬性表(method_info):表示方法中定義某一個屬性淆珊。其中涵蓋了屬性的所有信息。

4.6.1.9.1 Code屬性中屬性類型

Code屬性中定義的屬性主要有“LineNumberTable”類型和“LocalVariableTable”類型

  • “LineNumberTable”類型的屬性表記錄著Java源碼和機器指令之間的對應(yīng)關(guān)系
  • “LocalVariableTable”類型的屬性表記錄著局部變量描述
4.6.1.9.2 Java虛擬機定義的LineNumberTable
image
  • attribute_name_index,屬性名稱索引奸汇,占有2個字節(jié)施符,其內(nèi)的值指向了常量池中的某一項,該項表示字符串“LineNumberTable”;

  • attribute_length,屬性長度擂找,占有 4個字節(jié)戳吝,其內(nèi)的值表示后面有多少個字節(jié)是屬于此LineNumberTable屬性表的;

  • line_number_table_length:描述line_number_table結(jié)構(gòu)的數(shù)量

  • line_number_table:用來描述一行Java源碼和機器指令之間的對應(yīng)關(guān)系

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

名稱 字節(jié)長度 含義
start_pc 2個字節(jié) 字節(jié)碼行號
line_number 2個字節(jié) java 源碼行號
4.6.1.9.3 Java虛擬機定義的LocalVariableTable

[圖片上傳失敗...(image-2d7657-1564563120952)]%20%E5%B1%9E%E6%80%A7.png)

  • attribute_name_index,屬性名稱索引贯涎,占有2個字節(jié)听哭,其內(nèi)的值指向了常量池中的某一項,該項表示字符串“LocalVariableTable”;

  • attribute_length,屬性長度塘雳,占有 4個字節(jié)陆盘,其內(nèi)的值表示后面有多少個字節(jié)是屬于此LineNumberTable屬性表的;

  • local_variable_table_length:描述local_variable_table結(jié)構(gòu)的數(shù)量

  • local_variable_table:項目代表了一個棧幀與源碼中的局部變量的關(guān)聯(lián)

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

image
  • start_pc 和 length 屬性:分別代表了 這個局部變量的生命周期開始的字節(jié)碼偏移量及其作用范圍長度败明,兩者結(jié)合起來就是這個局部變量在字節(jié)碼中的作用域范圍隘马;

  • name_index 和 desc_index: 都是指向常量池中 CONSTANT_Utf8_info 型常量的索引,分別代表了局部變量的名稱以及這個局部變量的描述符妻顶;

  • index:是這個局部變量在棧幀局部變量表中Slot的位置酸员。當(dāng)這個變量是 64 位類型時,它占用的Slot 為 index and index + 1;

  • LocalVariableTable屬性:它增加了一個姐妹屬性——LocalVariableTypeTable讳嘱,這個新增的屬性結(jié)構(gòu)與LocalVariableTable 非常相似幔嗦,僅僅是把記錄的字段描述符的desc_index 替換為字段的特征簽名,對于非泛型類型來說沥潭, 描述符和特征簽名能描述的信息是基本一致的邀泉,但是泛型引入后,由于描述符中泛型的參數(shù)化類型被擦除掉钝鸽,描述符就不能正確地描述泛型類型了汇恤,所以就引入了LocalVariableTypeTable了;

如果不太理解可以看下圖

image
4.6.1.9.4 Javap反編譯結(jié)果
 LineNumberTable:
        line 6: 0
        line 7: 2
        line 8: 4
        line 9: 8
        line 13: 15
        line 14: 23
        line 10: 26
        line 11: 27
        line 13: 35
        line 14: 43
        line 13: 46
        line 15: 59
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            2      13     1     a   I
            4      11     2     b   I
            8       7     3     c   I
           27       8     1     e   Ljava/lang/Exception;
            0      60     0  this   Ljvm/ClassStructureMethod;
4.6.2 Exceptions 屬性

Exception屬性是在方法表中與Code屬性平級的一項屬性寞埠,切勿與Code屬性中的異常混淆焊夸。Exception屬性的作用是列舉出方法中可能拋出的受查異常(Checked Exception)仁连,也就是方法描述時在 throws 關(guān)鍵字后面列舉的異常。

Java虛擬機定義的Exceptions

image
  • attribute_name_index,屬性名稱索引,占有2個字節(jié)饭冬,其內(nèi)的值指向了常量池中的某一項使鹅,該項表示字符串“Exceptions”;

  • attribute_length,屬性長度,占有 4個字節(jié)昌抠,其內(nèi)的值表示后面有多少個字節(jié)是屬于此Exceptions屬性表的患朱;

  • number_of_exception:描述方法中可能拋出的受查異常的數(shù)量

  • exception_index_table:表示異常的名稱索引,其內(nèi)的值指向了常量池中的某一項炊苫,該項表示字符串對應(yīng)異常的名稱;

示例中Exceptions屬性

image
  • 屬性名稱索引用2位字節(jié)(u2)來描述,對應(yīng)16進制0x001B裁厅,即十進制的27,27是常量池數(shù)組的一個下標(biāo)侨艾,指向常量池中一個常量执虹,通過對照javap中結(jié)果中對應(yīng)到一個CONSTANT_Utf8_info類型的常量(下標(biāo)#27),字符串值為"Exceptions"唠梨,表示屬性類型為"Exceptions"袋励。

  • 屬性長度用4位字節(jié)(u4)來描述,對應(yīng)16進制0x00000004,即十進制的4当叭,表示"Exceptions"屬性值長度為4個字節(jié)

  • 異常數(shù)量用2位字節(jié)(u2)來描述,對應(yīng)16進制0x0001茬故,即十進制的1,表示異常的數(shù)量為1

  • 異常的名稱索引用2位字節(jié)(u2)來描述,對應(yīng)16進制0x0006蚁鳖,即十進制的6磺芭,8是常量池數(shù)組的一個下標(biāo),指向常量池中一個常量才睹,通過對照javap中結(jié)果中對應(yīng)到一個CONSTANT_Class_info類型的常量(下標(biāo)#6),CONSTANT_Class_info類型常量其值轉(zhuǎn)換為整數(shù)37徘跪,指向常量池中一個常量,通過對照javap中結(jié)果中對應(yīng)到一個CONSTANT_Utf8_info類型的常量(下標(biāo)#37)琅攘,字符串值為"java/lang/Exception"垮庐。

4 總結(jié)

可以用一張圖來描述上訴方法的結(jié)構(gòu)

image

javap完整結(jié)果

Classfile /C:/work/project/juc-in-action/target/classes/jvm/ClassStructureMethod.class
  Last modified 2019-7-30; size 861 bytes
  MD5 checksum c291986bf1b6bc3997d2e13aff91e614
  Compiled from "ClassStructureMethod.java"
public class jvm.ClassStructureMethod
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #9.#30         // java/lang/Object."<init>":()V
   #2 = Fieldref           #31.#32        // java/lang/System.out:Ljava/io/PrintStream;
   #3 = Methodref          #33.#34        // java/io/PrintStream.println:(I)V
   #4 = String             #35            // finally
   #5 = Methodref          #33.#36        // java/io/PrintStream.println:(Ljava/lang/String;)V
   #6 = Class              #37            // java/lang/Exception
   #7 = String             #38            // catch
   #8 = Class              #39            // jvm/ClassStructureMethod
   #9 = Class              #40            // java/lang/Object
  #10 = Utf8               <init>
  #11 = Utf8               ()V
  #12 = Utf8               Code
  #13 = Utf8               LineNumberTable
  #14 = Utf8               LocalVariableTable
  #15 = Utf8               this
  #16 = Utf8               Ljvm/ClassStructureMethod;
  #17 = Utf8               greeting
  #18 = Utf8               a
  #19 = Utf8               I
  #20 = Utf8               b
  #21 = Utf8               c
  #22 = Utf8               e
  #23 = Utf8               Ljava/lang/Exception;
  #24 = Utf8               StackMapTable
  #25 = Class              #37            // java/lang/Exception
  #26 = Class              #41            // java/lang/Throwable
  #27 = Utf8               Exceptions
  #28 = Utf8               SourceFile
  #29 = Utf8               ClassStructureMethod.java
  #30 = NameAndType        #10:#11        // "<init>":()V
  #31 = Class              #42            // java/lang/System
  #32 = NameAndType        #43:#44        // out:Ljava/io/PrintStream;
  #33 = Class              #45            // java/io/PrintStream
  #34 = NameAndType        #46:#47        // println:(I)V
  #35 = Utf8               finally
  #36 = NameAndType        #46:#48        // println:(Ljava/lang/String;)V
  #37 = Utf8               java/lang/Exception
  #38 = Utf8               catch
  #39 = Utf8               jvm/ClassStructureMethod
  #40 = Utf8               java/lang/Object
  #41 = Utf8               java/lang/Throwable
  #42 = Utf8               java/lang/System
  #43 = Utf8               out
  #44 = Utf8               Ljava/io/PrintStream;
  #45 = Utf8               java/io/PrintStream
  #46 = Utf8               println
  #47 = Utf8               (I)V
  #48 = Utf8               (Ljava/lang/String;)V
{
  public jvm.ClassStructureMethod();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 3: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Ljvm/ClassStructureMethod;

  public void greeting() throws java.lang.Exception;
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=5, args_size=1
         0: iconst_1
         1: istore_1
         2: iconst_1
         3: istore_2
         4: iload_1
         5: iload_2
         6: iadd
         7: istore_3
         8: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
        11: iload_3
        12: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
        15: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
        18: ldc           #4                  // String finally
        20: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        23: goto          59
        26: astore_1
        27: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
        30: ldc           #7                  // String catch
        32: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        35: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
        38: ldc           #4                  // String finally
        40: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        43: goto          59
        46: astore        4
        48: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
        51: ldc           #4                  // String finally
        53: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        56: aload         4
        58: athrow
        59: return
      Exception table:
         from    to  target type
             0    15    26   Class java/lang/Exception
             0    15    46   any
            26    35    46   any
            46    48    46   any
      LineNumberTable:
        line 6: 0
        line 7: 2
        line 8: 4
        line 9: 8
        line 13: 15
        line 14: 23
        line 10: 26
        line 11: 27
        line 13: 35
        line 14: 43
        line 13: 46
        line 15: 59
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            2      13     1     a   I
            4      11     2     b   I
            8       7     3     c   I
           27       8     1     e   Ljava/lang/Exception;
            0      60     0  this   Ljvm/ClassStructureMethod;
      StackMapTable: number_of_entries = 3
        frame_type = 90 /* same_locals_1_stack_item */
          stack = [ class java/lang/Exception ]
        frame_type = 83 /* same_locals_1_stack_item */
          stack = [ class java/lang/Throwable ]
        frame_type = 12 /* same */
    Exceptions:
      throws java.lang.Exception
}
SourceFile: "ClassStructureMethod.java"

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市坞琴,隨后出現(xiàn)的幾起案子哨查,更是在濱河造成了極大的恐慌,老刑警劉巖剧辐,帶你破解...
    沈念sama閱讀 222,378評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件寒亥,死亡現(xiàn)場離奇詭異,居然都是意外死亡荧关,警方通過查閱死者的電腦和手機溉奕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,970評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來忍啤,“玉大人加勤,你說我怎么就攤上這事仙辟。” “怎么了鳄梅?”我有些...
    開封第一講書人閱讀 168,983評論 0 362
  • 文/不壞的土叔 我叫張陵叠国,是天一觀的道長。 經(jīng)常有香客問我戴尸,道長粟焊,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,938評論 1 299
  • 正文 為了忘掉前任孙蒙,我火速辦了婚禮项棠,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘马篮。我一直安慰自己沾乘,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,955評論 6 398
  • 文/花漫 我一把揭開白布浑测。 她就那樣靜靜地躺著翅阵,像睡著了一般。 火紅的嫁衣襯著肌膚如雪迁央。 梳的紋絲不亂的頭發(fā)上掷匠,一...
    開封第一講書人閱讀 52,549評論 1 312
  • 那天,我揣著相機與錄音岖圈,去河邊找鬼讹语。 笑死,一個胖子當(dāng)著我的面吹牛蜂科,可吹牛的內(nèi)容都是我干的顽决。 我是一名探鬼主播,決...
    沈念sama閱讀 41,063評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼导匣,長吁一口氣:“原來是場噩夢啊……” “哼才菠!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起贡定,我...
    開封第一講書人閱讀 39,991評論 0 277
  • 序言:老撾萬榮一對情侶失蹤赋访,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后缓待,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蚓耽,經(jīng)...
    沈念sama閱讀 46,522評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,604評論 3 342
  • 正文 我和宋清朗相戀三年旋炒,在試婚紗的時候發(fā)現(xiàn)自己被綠了步悠。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,742評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡瘫镇,死狀恐怖鼎兽,靈堂內(nèi)的尸體忽然破棺而出芹壕,到底是詐尸還是另有隱情,我是刑警寧澤接奈,帶...
    沈念sama閱讀 36,413評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站通孽,受9級特大地震影響序宦,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜背苦,卻給世界環(huán)境...
    茶點故事閱讀 42,094評論 3 335
  • 文/蒙蒙 一互捌、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧行剂,春花似錦秕噪、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,572評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至铲觉,卻和暖如春澈蝙,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背撵幽。 一陣腳步聲響...
    開封第一講書人閱讀 33,671評論 1 274
  • 我被黑心中介騙來泰國打工灯荧, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人盐杂。 一個月前我還...
    沈念sama閱讀 49,159評論 3 378
  • 正文 我出身青樓逗载,卻偏偏與公主長得像,于是被迫代替她去往敵國和親链烈。 傳聞我的和親對象是個殘疾皇子厉斟,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,747評論 2 361