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

1、Code属性表结构:

数据类型名称数量
u2attribute_name_index1
u4attribute_length1
u2max_stack1
u2max_locals1
u4code_length1
u1codecode_length
u2exception_table_length1
exception_infoexception_tableexception_table_length
u2attribute_count1
attribute_infoattributesattribute_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、异常表的结构:

类型名称数量
u2start_pc1
u2end_pc1
u2handler_1
u2catch_type1
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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值