类文件结构之三:属性表(attribute_info)集合

来源:互联网 发布:淘宝卖家规则大全2017 编辑:程序博客网 时间:2024/06/03 09:56

1、Code属性表结构:

数据类型 名称 数量 u2 attribute_name_index 1 u4 attribute_length 1 u2 max_stack 1 u2 max_locals 1 u4 code_length 1 u1 code code_length u2 exception_table_length 1 exception_info exception_table exception_table_length u2 attribute_count 1 attribute_info attributes attribute_count

2、看二进制实例:
这里写图片描述

max_stack操作数栈operand Stacks)深度的最大值,虚拟机运行时根据此分配栈帧(stack frame),max_locals局部变量表所需的空间,Slot为单位,对于boolean,byte,char,short,int,float,returnAddress等长度不超过32位的数据类型,每个数据类型占一个Slot。code为字节码指令

属性26  0x105  0x0009 0000 002F 0001 0001 0000 0005 2AB7 000A B1 其中0x0009指向属性名称的索引,0x0000 002F属性值长度(为属性表长度-6,因为名称和属性长度共占6字节),0x0001为max_stack, 0x0001为max_locals, 0x0000 0005为长度字节码指令长度,2AB7 000A B1

Code属性是Class文件中最重要的属性,如果把JAVA程序中的信息分为代码(Code,方法体中的代码)和元数据(Metadata,类、字段、方法定义及其他信息)两部分,在整个class文件中,Code属性用于描述代码,所有的其他数据项目都用于描述元数据。

3、接着查看“2AB7 000A B1”:

  • 0x2A的指令为aload_0:将第0个Slot中为reference类型的本地变量放到操作数栈顶;
  • 0xB7为指令invokespecial,以栈顶的reference类型数据指向的对象作为方法的接收者,调用此对象的
    • 实例构造器方法;
    • private方法
    • 父类方法
      接着一个u2的参数说明具体调用哪个方法
  • 0x000A ,为invokespecial的参数,查常量池得“< init>”
  • 0xB1,为指令return,返回方法,返回类型为void

4、 通过javap查看的信息:

{  public jvm.loadingclass.TestClass();    descriptor: ()V    flags: ACC_PUBLIC    Code:      stack=1, locals=1, args_size=1         0: aload_0         1: invokespecial #10                 // Method java/lang/Object."<init>":()V         4: return      LineNumberTable:        line 3: 0      LocalVariableTable:        Start  Length  Slot  Name   Signature            0       5     0  this   Ljvm/loadingclass/TestClass;  public int inc();    descriptor: ()I    flags: ACC_PUBLIC    Code:      stack=2, locals=1, args_size=1         0: aload_0         1: getfield      #18                 // Field m:I         4: iconst_1         5: iadd         6: ireturn      LineNumberTable:        line 6: 0      LocalVariableTable:        Start  Length  Slot  Name   Signature            0       7     0  this   Ljvm/loadingclass/TestClass;}
  • 注意到Args_size =1,在< init>()实例构造器和inc()方法中并没有参数,也没有定义局部变量,但是Locals=1。在任何实例方法中,都可以通过this来获得当前对象的引用,实际上是javac编译器编译时,每个实例方法都会传入this这个参数,导致所有的实例方法的局部变量表都会有this,所以我们看到Args_size=1,Locals=1。如果inc为static,那么Args_size=0,Locals=0

注:this代表调用这个方法的对象引用

5、异常表的结构:

类型 名称 数量 u2 start_pc 1 u2 end_pc 1 u2 handler_ 1 u2 catch_type 1
public class TestClass {    public int inc() {        int x ;        try{            x = 1;            return x;        }catch(Exception e){            x = 2;        }finally{            x = 3;        }        return 0;    }}
  public int inc();    descriptor: ()I    flags: ACC_PUBLIC    Code:      stack=1, locals=5, args_size=1         0: iconst_1         1: istore_1         2: iload_1         3: istore        4         5: iconst_3         6: istore_1         7: iload         4         9: ireturn        10: astore_2        11: iconst_2        12: istore_1        13: iconst_3        14: istore_1        15: goto          23        18: astore_3        19: iconst_3        20: istore_1        21: aload_3        22: athrow        23: iconst_0        24: ireturn      Exception table:         from    to  target type             0     5    10   Class java/lang/Exception             0     5    18   any            10    13    18   any

(这里之后书上本章大多是理论说明,先不细看,学习后面的类加载机制,再往回来细看)

阅读全文
0 0
原创粉丝点击