JVM学习笔记12 - 解读笔记11中的attributes

bilibili-JVM学习笔记12 - 解读笔记11中的attributes
The Java Virtual Machine Specification - Java SE 8 Edition

JVM学习笔记11 - Java字节码初识

4.7. Attributes

附加属性

attribute_info {
    u2 attribute_name_index;
    u4 attribute_length;
    u1 info[attribute_length];
}
Table 4.7-A. Predefined class file attributes (by section)
AttributeSectionclass fileJava SE
ConstantValue§4.7.245.31.0.2
Code§4.7.345.31.0.2
StackMapTable§4.7.450.06
Exceptions§4.7.545.31.0.2
InnerClasses§4.7.645.31.1
EnclosingMethod§4.7.749.05.0
Synthetic§4.7.845.31.1
Signature§4.7.949.05.0
SourceFile§4.7.1045.31.0.2
SourceDebugExtension§4.7.1149.05.0
LineNumberTable§4.7.1245.31.0.2
LocalVariableTable§4.7.1345.31.0.2
LocalVariableTypeTable§4.7.1449.05.0
Deprecated§4.7.1545.31.1
RuntimeVisibleAnnotations§4.7.1649.05.0
RuntimeInvisibleAnnotations§4.7.1749.05.0
RuntimeVisibleParameterAnnotations§4.7.1849.05.0
RuntimeInvisibleParameterAnnotations§4.7.1949.05.0
RuntimeVisibleTypeAnnotations§4.7.2052.08
RuntimeInvisibleTypeAnnotations§4.7.2152.08
AnnotationDefault§4.7.2249.05.0
BootstrapMethods§4.7.2351.07
MethodParameters§4.7.2452.08
4.7.3. The Code Attribute
Code_attribute {
    u2 attribute_name_index;
    u4 attribute_length;
    u2 max_stack;
    u2 max_locals;
    u4 code_length;
    u1 code[code_length];
    u2 exception_table_length;
    {   u2 start_pc;
        u2 end_pc;
        u2 handler_pc;
        u2 catch_type;
    } exception_table[exception_table_length];
    u2 attributes_count;
    attribute_info attributes[attributes_count];
}
4.7.12. The LineNumberTable Attribute
LineNumberTable_attribute {
    u2 attribute_name_index;
    u4 attribute_length;
    u2 line_number_table_length;
    {   u2 start_pc;
        u2 line_number;	
    } line_number_table[line_number_table_length];
}
4.7.13. The LocalVariableTable Attribute
LocalVariableTable_attribute {
    u2 attribute_name_index;
    u4 attribute_length;
    u2 local_variable_table_length;
    {   u2 start_pc;
        u2 length;
        u2 name_index;
        u2 descriptor_index;
        u2 index;
    } local_variable_table[local_variable_table_length];
}

解析 method_info[0]

  • access_flags u2
    • 00010007 --> 查询 Table 4.6-A --> = 0x0001 --> ACC_PUBLIC
  • name_index u2
    • 00010007 --> 指向常量池索引 7 --> --> 表示此方法为构造方法
  • descriptor_index u2
    • 00080001 --> 指向常量池索引 8 --> ()V --> () 内无参数表示此构造方法为无参构造器
  • attributes_count u2
    • 00080001 --> 1 个 attribute_info
  • attributes[attributes_count] attribute_info
  • attributes[0]
    • attribute_name_index u2
      • 00090000 --> 指向常量池索引 9 --> Code
    • attribute_length u4
      • 00090000 00380002 --> 长度 56
    • info[attribute_length] u1
      • 长度 * u1
      • 00380002 00010000 000A2AB7 00012A04 B50002B1 00000002 000A0000 000A0002 00000003 00040005 000B0000 000C0001 0000000A 000C000D 00000001 --> 详细信息如下:
      • max_stack u2
        • 00380002 --> 2 --> max_stack 项的值给出该方法执行过程中任意时刻该方法的操作数堆栈的最大深度(第2.6.2节)
      • max_locals u2
        • 00010000 --> 1 --> max_locals 项目的值给出在调用此方法(第2.6.1节)时分配的局部变量数组中的局部变量数,包括用于在调用该方法时将参数传递给该方法的局部变量。long 或 double 类型的值的最大局部变量索引是 max_locals-2。max_locals-1 是任何其他类型的值的最大局部变量索引。
      • code_length u4
        • 00010000 000A2AB7 --> 10 --> code_length 项的值给出此方法在代码数组中的字节数。code_length的值必须大于零(因为代码数组不能为空)且小于65536。
      • code[code_length] u1
        • 000A2AB7 00012A04 B50002B1 --> 解析成指令集
          • 0x2A --> 查询jvm指令集 --> aload_0
            • 没有参数
          • 0xB7 --> invokespecial
            • 有一个参数 0001 --> #1 --> java/lang/Object."<init>":()V
          • 0x2A --> aload_0
          • 0x04 --> 0x4 --> iconst_1
          • 0xB5 --> putfield
            • 0002 --> #2 --> new_package/jvm/p37/MyTest1.a:I
          • 0xB1 --> return
      • exception_table_length u2
        • 00000002 --> 0
      • exception_table {…}
      • attributes_count u2
        • 00000002 --> 2 个附加属性
      • attribute_info attributes[attributes_count]
      • attributes[0]
        • attribute_name_index u2
          • 000A0000 --> 10 --> LineNumberTable
        • attribute_length u4
          • 000A0000 000A0002 --> 10
        • info[attribute_length] u1
          • 000A0002 00000003 00040005 --> LineNumberTable Attribute
          • line_number_table_length u2
            • 000A0002 --> 2
          • line_number_table[line_number_table_length]
            • line_number_table[0]
              • start_pc u2
                • 00000003 --> 0
              • line_number u2
                • 00000003 --> 3
            • line_number_table[1]
              • start_pc u2
                • 00040005 --> 4
              • line_number u2
                • 00040005 --> 5
      • attributes[1]
        • attribute_name_index u2
          • 000B0000 --> 11 --> LocalVariableTable
        • attribute_length u4
          • 000B0000 000C0001 --> 12
        • info[attribute_length] u1
          • 000C0001 0000000A 000C000D 00000001 --> LocalVariableTable Attribute
          • local_variable_table_length u2
            • 000C0001 --> 1
          • local_variable_table[local_variable_table_length]
            • local_variable_table[0]
              • start_pc u2
                • 0000000A --> 0
              • length u2
                • 0000000A --> 10
              • name_index u2
                • 000C000D --> this
              • descriptor_index u2
                • 000C000D --> Lnew_package/jvm/p37/MyTest1;
              • index u2
                • 00000001 --> 0

解析 method_info[1]

  • access_flags u2
    • 00000001 --> 查询 Table 4.6-A --> = 0x0001 --> ACC_PUBLIC
  • name_index u2
    • 000E000F --> 指向常量池索引 14 --> getA --> 方法名
  • descriptor_index u2
    • 000E000F --> 指向常量池索引 15 --> ()I --> 方法描述符
  • attributes_count u2
    • 00010009 --> 1 个 attribute_info
  • attributes[attributes_count] attribute_info
  • attributes[0]
    • attribute_name_index u2
      • 00010009 --> 指向常量池索引 9 --> Code
    • attribute_length u4
      • 0000002F --> 长度 47
    • info[attribute_length] u1
      • 长度 * u1
      • 00010001 00000005 2AB40002 AC000000 02000A00 00000600 01000000 08000B00 00000C00 01000000 05000C00 0D000000 -->
      • max_stack u2
        • 00010001 --> 1
      • max_locals u2
        • 00010001 --> 1
      • code_length u4
        • 00000005 --> 5
      • code[code_length] u1
        • 2AB40002 AC000000
          • 0x2A --> aload_0
          • 0xB4 --> getfield
            • 0002 --> #2 --> new_package/jvm/p37/MyTest1.a:I
          • 0xAC --> ireturn
      • exception_table_length u2
        • AC000000 --> 0
      • exception_table {…}
      • attributes_count u2
        • AC000000 02000A00 --> 2 个附加属性
      • attribute_info attributes[attributes_count]
      • attributes[0]
        • attribute_name_index u2
          • 02000A00 --> 10 --> LineNumberTable
        • attribute_length u4
          • 02000A00 00000600 --> 6
        • info[attribute_length] u1
          • 00000600 01000000 08000B00 --> LineNumberTable Attribute
          • line_number_table_length u2
            • 00000600 01000000 --> 1
          • line_number_table[line_number_table_length]
            • line_number_table[0]
              • start_pc u2
                • 01000000 --> 0
              • line_number u2
                • 01000000 08000B00 --> 8
      • attributes[1]
        • attribute_name_index u2
          • 08000B00 --> 11 --> LocalVariableTable
        • attribute_length u4
          • 08000B00 00000C00 --> 12
        • info[attribute_length] u1
          • 00000C00 01000000 05000C00 0D000000 --> LocalVariableTable Attribute
          • local_variable_table_length u2
            • 00000C00 01000000 --> 1
          • local_variable_table[local_variable_table_length]
            • local_variable_table[0]
              • start_pc u2
                • 01000000 --> 0
              • length u2
                • 01000000 05000C00 --> 5
              • name_index u2
                • 05000C00 --> this
              • descriptor_index u2
                • 05000C00 0D000000 --> Lnew_package/jvm/p37/MyTest1;
              • index u2
                • 0D000000 --> 0

资料

  • 方法(method_info)中的每个属性都是一个 attribute_info 结构;
  • 方法属性结构
    • JVM 预定义了部分 attribute ,但是编译器自己也可以实现自己的 attribute 写入 class 文件里,供运行时使用;
    • 不同的 attribute 通过 attribute_name_index 来区分
  • Code 属性结构
    • attribute_name_index 名称
    • attribute_length 表示 attribute 所包含的字节数,不包含 attribute_name_index 和 attribute_length 字段
    • max_stack 表示这个方法运行的任何时刻所能达到的操作数栈的最大深度
    • max_locals 表示方法执行期间创建的局部变量的数目,包含用来表示传入的参数的局部变量
    • code_length 表示该方法所包含的字节码的字节数以及具体的指令码
      • 具体字节码即是该方法被调用时,阻尼及所执行的字节码
    • exception_table 这里存放的是处理异常的信息
      • 每个 exception_table 表项由 start_pc,end_pc,handler_pc,catch_type 组成
      • start_pc 和 end_pc 表示在 code 数组中从 start_pc 到 end_pc 处(包含 start_pc ,不包含 end_pc)的指令抛出的异常会由这个表项处理
      • handler_pc 表示处理异常的代码的开始处(catch{…})
      • catch_type 表示会被处理的异常类型,它指向常量池里的一个异常类,当 catch_type 为 0 时,表示处理所有的异常

工具

字节码查看工具

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值