Java类文件 属性表集合

Java类文件中,每个字段表和方法表都可以包含属性表集合,用于存储与这些字段或方法相关的元数据信息。属性表集合的结构和常量池类似,也是由个数和属性表集合数组构成,属性表集合数组的每个元素都是一个属性表。

属性表的结构如下:

attribute_info {
    u2 attribute_name_index;
    u4 attribute_length;
    u1 info[attribute_length];
}

其中,attribute_name_index 是一个常量池索引,指向一个 CONSTANT_Utf8_info 常量,用于表示属性名。attribute_length 是一个无符号 4 字节整数,表示属性值的长度,单位是字节。info 数组中存储了具体的属性值信息。

Java 虚拟机规范中定义了很多种不同的属性类型,包括 Code、ConstantValue、Exceptions、LineNumberTable、LocalVariableTable、SourceFile 等等。这些属性表用于存储各种类型的元数据信息,例如方法的字节码、局部变量表、异常处理器等等。

下面是一个示例,展示了一个方法表中包含多个属性表的情况:

public class MyClass {
    private int a;
    public void setA(int a) {
        this.a = a;
    }
}

将该类编译成字节码后,可以使用 javap 工具查看字节码文件的属性表集合。下面是一个示例:

$ javap -v MyClass.class

Classfile /path/to/MyClass.class
  Last modified 2022-02-21; size 310 bytes
  MD5 checksum 163c0778de773c1cb15f5d2b5c5e9208
  Compiled from "MyClass.java"
public class MyClass
  minor version: 0
  major version: 59
  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
  this_class: #6                          // MyClass
  super_class: #7                         // java/lang/Object
  interfaces: 0, fields: 1, methods: 1, attributes: 1
Constant pool:
   #1 = Methodref          #7.#22         // java/lang/Object."<init>":()V
   #2 = Fieldref           #6.#23         // MyClass.a:I
   #3 = Methodref          #6.#24         // MyClass.setA:(I)V
   #4 = Utf8               a
   #5 = Utf8               I
   #6 = Class              #25            // MyClass
   #7 = Class              #26            // java/lang/Object
   #8 = Utf8               <init>
   #9 = Utf8               ()V
  #10 = Utf8               Code
  #11 = Utf8               LineNumberTable
  #12 = Utf8               LocalVariableTable
  #13 = Utf8               this
  #14 = Utf8               LMyClass;
  #15 = Utf8               setA
  #16 = Utf8               (I)V
  #17 = Utf8               SourceFile
  #18 = Utf8               MyClass.java
  #19 = Utf8               InnerClasses
  #20 = Utf8               MyClass
  ......