Java虚拟机-Class文件结构之方法表

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 方法表前置结构

image
  • 类访问标志2个字节(u2)来描述,对应16进制0x0021,对照Java虚拟机规范定义,匹配ACC_PUBLIC、ACC_SUPER,表示当前类的修饰符为public。

  • 类名用2位字节(u2)来描述,对应16进制0x0008,即十进制的8,8是常量池数组的一个下标,指向常量池中一个常量,通过对照javap中结果中对应到一个CONSTANT_Class_info类型的常量(下标#8),CONSTANT_Class_info类型常量其值转换为整数20,指向常量池中一个常量,通过对照javap中结果中对应到一个CONSTANT_Utf8_info类型的常量(下标#39),字符串值为"jvm/ClassStructureMethod"。

  • 父类名用2位字节(u2)来描述,对应16进制0x0009,即十进制的9,9是常量池数组的一个下标,指向常量池中一个常量,通过对照javap中结果中对应到一个CONSTANT_Class_info类型的常量(下标#9),CONSTANT_Class_info类型常量其值转换为整数21,指向常量池中一个常量,通过对照javap中结果中对应到一个CONSTANT_Utf8_info类型的常量(下标#40),字符串值为"java/lang/Object"。

  • 类接口数量用2位字节(u2)来描述,对应16进制0x0000,即十进制的0,表示当前类没有实现接口。因此Class文件中不存在接口名称描述。

  • 字段数量用2位字节(u2)来描述,对应16进制0x0000,即十进制的0,表示当前类没有字段。因此Class文件中不存在字段的描述。

2 方法表结构

方法表集合的结构

方法表集合的结构被划分为方法表数量方法表集合。

方法表数量(methods_count):表示类中定义的方法个数,其中除了自定义的方法外,每一个类中都会存在名称为"<init>"构造函数,如果类中定义静态变量或者静态块,则还会存在一个名称为"<clinit>"类初始化方法。

方法表(method_info):表示类中定义某一个方法。其中涵盖了方法的所有信息。

image

3 方法表数量(methods_count)

Java虚拟机规范中方法表数量用2个字节(u2)用来表示。

示例中方法表数量

示例中方法数量,对应16进制0x0002,即十进制的2,代表Class文件中有2个方法。

image

对比源代码中ClassStructureMethod类定义,存在一个构造方法<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方法的描述

本章节主要用来解析greeting方法在Class文件中的结构,在此跳过<init>方法部分描述。

Class文件中init方法的描述

image

4 方法表(methods_info)

Java虚拟机规范定义方法表结构

image
  • 方法访问标志(access_flags)
  • 方法名称索引(name_index)
  • 方法描述符索引(descriptor_index)
  • 方法属性表集合(attributes)
4.1 方法访问标志(access_flags)

Java虚拟机规范中方法访问标志用2个字节(u2)用来表示。

Java虚拟机规范定义方法访问标志

image

示例中方法访问标志

字段修饰符用2个字节(u2)来描述,对应16进制0x0001,对照JVM规范表中方法方法访问标志为ACC_PUBLIC,表示方法被"public"修饰

image

对比源代码中可以发现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虚拟机规范中方法名称用2个字节(u2)用来表示。可以换算成为一个整数,这个整数是常量池数组的一个下标,指向中一个CONSTANT_Utf8_info类型的常量用来描述方法的名称。

示例方法名称

方法名用2位字节(u2)来描述,对应16进制0x0011,即十进制的17,17是常量池数组的一个下标,指向常量池中一个常量,通过对照javap中结果中对应到一个CONSTANT_Utf8_info类型的常量(下标#17),对应字符串"greeting",表示方法名称

image
4.3 方法描述符(descriptor_index)

按照Java虚拟机规范方法描述符用2位字节(u2)来描述,可以换算成为一个整数,这个整数是常量池数组的一个下标,指向中一个CONSTANT_Utf8_info类型的常量用来描述方法描述符。

关于方法的描述符在常量池中讲过主要用来描述方法的参数和返回类型。

示例中方法描述符

方法修饰符用2个字节(u2)描述,对应16进制0x000B,即十进制的11,11是常量池数组的一个下标,指向常量池中一个常量,通过对照javap中结果中对应到一个CONSTANT_Utf8_info类型的常量(下标#11),对应字符串"()V",表示greeting方法不需要传递参数,且不需要返回值

image

4.4 方法中的属性

4.4.1 属性表

属性表(attribute_info)作用于Class文件、字段表、方法表。它们都可以携带自己的属性集合,用于描述某些场景专有的信息。

4.4.2 虚拟机规范中定义属性表类型
image
4.4.3 属性表集合的结构

属性表集合的结构被划分为属性表数量属性表集合。

属性表数量(methods_count):表示方法中定义的属性个数。

属性表(method_info):表示方法中定义某一个属性。其中涵盖了属性的所有信息。

4.4.4 用于方法中属性表

对于方法来说常用到的属性有如下几种:"code","Exception","Deprecated","Synthetic"。

  • code:用来表示方法中java字节码

  • Exception:用来记录方法中的异常信息。

  • Deprecated:用来表示方法是否被@Deprecated修饰

  • Synthetic:表示方法是否被编译器自动生成。

4.4.5 属性表通用格式

属性名称索引:属性名称索引占用2个字节,可以换算成为一个整数,这个整数是常量池数组的一个下标,指向中一个CONSTANT_Utf8_info类型的常量用来描述属性名称。通过属性名称就可以确定属性表类型

属性长度:占用4个字节,它的值表示紧跟其后的多少个字节是拿来表示这个属性信息的。

属性值:由若个个字节构造,字节的大小取决属性的长度

image

4.5 属性表数量

Java虚拟机规范中属性表数量用2个字节(u2)用来表示。

示例中属性表数量

示例中属性表,对应16进制0x0002,即十进制的2,代表方法中有2个属性。

image

4.6 属性表

4.6.1 Code属性
4.6.1.1 Code属性名称索引

属性名称索引用2个字节(u2)描述,对应16进制0x000C,即十进制的12,12是常量池数组的一个下标,指向常量池中一个常量,通过对照javap中结果中对应到一个CONSTANT_Utf8_info类型的常量(下标#12),对应字符串"code",表示当前属性code类型的属性。

image
4.6.1.2 Code属性结构

通过属性名称索引知道了方法的第一个索引名称为"code".其虚拟机规范中的定义如下:

image
  • attribute_name_index,属性名称索引,占有2个字节,其内的值指向了常量池中的某一项,该项表示字符串“Code”;
  • attribute_length,属性长度,占有 4个字节,其内的值表示后面有多少个字节是属于此Code属性表的;
  • max_stack,操作数栈深度的最大值,占有 2 个字节,在方法执行的任意时刻,操作数栈都不应该超过这个值,虚拟机的运行的时候,会根据这个值来设置该方法对应的栈帧(Stack Frame)中的操作数栈的深度;
  • max_locals,最大局部变量数目,占有 2个字节,其内的值表示局部变量表所需要的存储空间大小;
  • code_length,Java字节码的长度,占有 4 个字节,表示跟在其后的多少个字节表示的是机器指令;
  • code,Java字节码,该区域占有的字节数目由 code_length中的值决定。JVM最底层的要执行的Java字节码指令就存储在这里;
  • exception_table_length,显式异常表长度,占有2个字节,如果在方法代码中出现了try{} catch()形式的结构,该值不会为空,紧跟其后会跟着若干个exception_table结构体,以表示异常捕获情况;
  • exception_table,显式异常表,占有8 个字节,start_pc,end_pc,handler_pc中的值都表示的是PC计数器中的指令地址。exception_table表示的意思是:如果字节码从第start_pc行到第end_pc行之间出现了catch_type所描述的异常类型,那么将跳转到handler_pc行继续处理。
  • attribute_count,属性计数器,占有 2 个字节,表示Code属性表的其他属性的数目
  • attribute_info,表示Code属性表具有的属性表,它主要分为两个类型的属性表:“LineNumberTable”类型和“LocalVariableTable”类型。
  • “LineNumberTable”类型的属性表记录着Java源码和机器指令之间的对应关系
  • “LocalVariableTable”类型的属性表记录着局部变量描述
4.6.1.3 Code属性长度

属性长度索引用4个字节(u4)描述,对应16进制0x000000EB,即十进制的235,表示属性的长度占用235个字节

image
4.6.1.4 Code属性max_stack

操作数栈深度的最大值用2个字节(u2)描述,对应16进制0x002,即十进制的2,表示方法中操作数栈深度最大值为2

image
4.6.1.5 Code属性max_locals

最大局部变量数目用2个字节(u2)描述,对应16进制0x005,即十进制的5,表示最大局部变量数目为5

image
4.6.1.6 Code属性code_length

java字节码的长度用4个字节(u4)描述,对应16进制0x0000003C,即十进制的60,表示ava字节码的长度为60

image
4.6.1.7 Code属性code

java字节码的长度用60个字节描述

image
4.6.1.8 Code属性中异常表集合

异常表集合的结构被划分为异常表数量异常表集合。

异常表数量(exceptions_count):表示方法代码中可能存在抛出异常个数。

异常表(exception_info):表示代码中一个异常。

4.6.1.8.1 Code属性中异常表数量

Code属性中异常表数量用2个字节(u2)描述,对应16进制0x004,即十进制的4,表示异常表数量为4

image
4.6.1.8.2 Code属性中异常表结构

异常表用来表示的意思是:如果字节码从第start_pc行到第end_pc行之间出现了catch_type所描述的异常类型,那么将跳转到handler_pc行继续处理

名称 字节长度 含义
start_pc 2个字节 异常发生起始字节指令行
end_pc 2个字节 异常发生结束字节指令行
handler_pc 2个字节 异常处理字节指令行
catch_type 2个字节 异常类型
  • 异常发生起始字节指令行用2个字节(u2)描述,对应16进制0x0000,即十进制的0,表示异常发生起始字节指令行为0

  • 异常发生结束字节指令行用2个字节(u2)描述,对应16进制0x000f,即十进制的15,表示异常发生结束字节指令行为15

  • 异常处理字节指令行用2个字节(u2)描述,对应16进制0x001A,即十进制的26,表示异常处理字节指令行为26

  • 异常类型用2个字节(u2)描述,对应16进制0x0006,即十进制的6,6是常量池数组的一个下标,指向常量池中一个常量,通过对照javap中结果中对应到一个CONSTANT_Utf8_info类型的常量(下标#6),对应字符串"java/lang/Exception"

image

这里同样可以使用javap反编译工具来解析获取。我们在此比对下,需要注意的是这里行表示的是反编译工具中字节指令的行而非源代码中的行

       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属性内部同样有属性集合

属性表集合的结构同样被划分为属性表数量和属性表集合。

属性表数量(methods_count):表示方法中定义的属性个数。

属性表(method_info):表示方法中定义某一个属性。其中涵盖了属性的所有信息。

4.6.1.9.1 Code属性中属性类型

Code属性中定义的属性主要有“LineNumberTable”类型和“LocalVariableTable”类型

  • “LineNumberTable”类型的属性表记录着Java源码和机器指令之间的对应关系
  • “LocalVariableTable”类型的属性表记录着局部变量描述
4.6.1.9.2 Java虚拟机定义的LineNumberTable
image
  • attribute_name_index,属性名称索引,占有2个字节,其内的值指向了常量池中的某一项,该项表示字符串“LineNumberTable”;

  • attribute_length,属性长度,占有 4个字节,其内的值表示后面有多少个字节是属于此LineNumberTable属性表的;

  • line_number_table_length:描述line_number_table结构的数量

  • line_number_table:用来描述一行Java源码和机器指令之间的对应关系

line_number_table结构

名称 字节长度 含义
start_pc 2个字节 字节码行号
line_number 2个字节 java 源码行号
4.6.1.9.3 Java虚拟机定义的LocalVariableTable

[图片上传失败...(image-2d7657-1564563120952)]%20%E5%B1%9E%E6%80%A7.png)

  • attribute_name_index,属性名称索引,占有2个字节,其内的值指向了常量池中的某一项,该项表示字符串“LocalVariableTable”;

  • attribute_length,属性长度,占有 4个字节,其内的值表示后面有多少个字节是属于此LineNumberTable属性表的;

  • local_variable_table_length:描述local_variable_table结构的数量

  • local_variable_table:项目代表了一个栈帧与源码中的局部变量的关联

local_variable_table结构

image
  • start_pc 和 length 属性:分别代表了 这个局部变量的生命周期开始的字节码偏移量及其作用范围长度,两者结合起来就是这个局部变量在字节码中的作用域范围;

  • name_index 和 desc_index: 都是指向常量池中 CONSTANT_Utf8_info 型常量的索引,分别代表了局部变量的名称以及这个局部变量的描述符;

  • index:是这个局部变量在栈帧局部变量表中Slot的位置。当这个变量是 64 位类型时,它占用的Slot 为 index and index + 1;

  • LocalVariableTable属性:它增加了一个姐妹属性——LocalVariableTypeTable,这个新增的属性结构与LocalVariableTable 非常相似,仅仅是把记录的字段描述符的desc_index 替换为字段的特征签名,对于非泛型类型来说, 描述符和特征签名能描述的信息是基本一致的,但是泛型引入后,由于描述符中泛型的参数化类型被擦除掉,描述符就不能正确地描述泛型类型了,所以就引入了LocalVariableTypeTable了;

如果不太理解可以看下图

image
4.6.1.9.4 Javap反编译结果
 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 关键字后面列举的异常。

Java虚拟机定义的Exceptions

image
  • attribute_name_index,属性名称索引,占有2个字节,其内的值指向了常量池中的某一项,该项表示字符串“Exceptions”;

  • attribute_length,属性长度,占有 4个字节,其内的值表示后面有多少个字节是属于此Exceptions属性表的;

  • number_of_exception:描述方法中可能抛出的受查异常的数量

  • exception_index_table:表示异常的名称索引,其内的值指向了常量池中的某一项,该项表示字符串对应异常的名称;

示例中Exceptions属性

image
  • 属性名称索引用2位字节(u2)来描述,对应16进制0x001B,即十进制的27,27是常量池数组的一个下标,指向常量池中一个常量,通过对照javap中结果中对应到一个CONSTANT_Utf8_info类型的常量(下标#27),字符串值为"Exceptions",表示属性类型为"Exceptions"。

  • 属性长度用4位字节(u4)来描述,对应16进制0x00000004,即十进制的4,表示"Exceptions"属性值长度为4个字节

  • 异常数量用2位字节(u2)来描述,对应16进制0x0001,即十进制的1,表示异常的数量为1

  • 异常的名称索引用2位字节(u2)来描述,对应16进制0x0006,即十进制的6,8是常量池数组的一个下标,指向常量池中一个常量,通过对照javap中结果中对应到一个CONSTANT_Class_info类型的常量(下标#6),CONSTANT_Class_info类型常量其值转换为整数37,指向常量池中一个常量,通过对照javap中结果中对应到一个CONSTANT_Utf8_info类型的常量(下标#37),字符串值为"java/lang/Exception"。

4 总结

可以用一张图来描述上诉方法的结构

image

javap完整结果

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"

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,402评论 6 499
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,377评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,483评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,165评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,176评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,146评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,032评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,896评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,311评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,536评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,696评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,413评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,008评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,815评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,698评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,592评论 2 353