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
......