方法表集合之后的属性表集合,指的是class文件所携带的辅助信息,比如该 class 文件的源文件的名称。以及任何带有RetentionPolicy.CLASS 或者RetentionPolicy.RUNTIME的注解。这类信息通常被用于Java虚拟机的验证和运行,以及Java程序的调试,一般无须深入了解。
此外,字段表、方法表都可以有自己的属性表。用于描述某些场景专有的信息。
属性表集合的限制没有那么严格,不再要求各个属性表具有严格的顺序,并且只要不与已有的属性名重复,任何人实现的编译器都可以向属性表中写入自己定义的属性信息,但Java虚拟机运行时会忽略掉它不认识的属性。
1、attributes_count (属性计数器)
attributes_count的值表示当前class文件属性表的成员个数。属性表中每一项都是一个attribute_info结构。
2 attributes [](属性表)
属性表的每个项的值必须是attribute_info结构。属性表的结构比较灵活,各种不同的属性只要满足以下结构即可。
2.1 属性的通用格式
即只需说明属性的名称以及占用位数的长度即可,属性表具体的结构可以去自定义。
2.2 属性类型
属性表实际上可以有很多类型,上面看到的Code属性只是其中一种,Java8里面定义了23种属性。
下面这些是虚拟机中预定义的属性:
或(查看官网)
1. ConstantValue 属性
ConstantValue 属性表示一个常量字段的值。位于 field_info结构的属性表中。
ConstantValue_attribute {
u2 attribute_name_index;
u4 attribute_length;
u2 constantvalue_index;//字段值在常量池中的索引,常量池在该索引处的项给出该属性表示的常量值。(例如,值是long型的,在常量池中便是CONSTANT_Long)
}
2. Deprecated 属性
Deprecated 属性是在 JDK 1.1 为了支持注释中的关键词@deprecated 而引入的。
Deprecated_attribute {
u2 attribute_name_index;
u4 attribute_length;
}
3. Code 属性
Code属性就是存放方法体里面的代码。但是,并非所有方法表都有Code属性。像接口或者抽象方法,他们没有具体的方法体,因此也就不会有Code属性了。 Code属性表的结构,如下图:
可以看到:Code属性表的前两项跟属性表是一致的,即Code属性表遵循属性表的结构,后面那些则是他自定义的结构。
4. InnerClasses 属性
为了方便说明特别定义一个表示类或接口的 Class 格式为 C。如果 C 的常量池中包含某个CONSTANT_Class_info 成员,且这个成员所表示的类或接口不属于任何一个包,那么 C 的ClassFile 结构的属性表中就必须含有对应的 InnerClasses 属性。InnerClasses 属性是在 JDK 1.1 中为了支持内部类和内部接口而引入的,位于 ClassFile结构的属性表。
5. LineNumberTable 属性
- LineNumberTable 属性是可选变长属性,位于 Code结构的属性表。
- LineNumberTable属性是用来描述Java源码行号与字节码行号之间的对应关系。这个属性可以用来在调试的时候定位代码执行的行数。
start_pc,即字节码行号;line_number,即Java源代码行号。 - 在 Code 属性的属性表中,LineNumberTable 属性可以按照任意顺序出现,此外,多个 LineNumberTable属性可以共同表示一个行号在源文件中表示的内容,即 LineNumberTable 属性不需要与源文件的行一一对应。
LineNumberTable属性表结构:
6. LocalVariableTable 属性
LocalVariableTable 是可选变长属性,位于 Code属性的属性表中。它被调试器用于确定方法在执行过程中局部变量的信息。 在 Code 属性的属性表中,LocalVariableTable 属性可以按照任意顺序出现。 Code 属性中的每个局部变量最多只能有一个 LocalVariableTable 属性。
- start pc + length表示这个变量在字节码中的生命周期起始和结束的偏移位置(this生命周期从头0到结尾)
- index就是这个变量在局部变量表中的槽位(槽位可复用)
- name就是变量名称
- Descriptor表示局部变量类型描述
LocalVariableTable 属性表结构:
7. Signature 属性
Signature 属性是可选的定长属性,位于 ClassFile, field_info 或 method_info结构的属性表中。在 Java 语言中,任何类、 接口、 初始化方法或成员的泛型签名如果包含了类型变量( Type Variables) 或参数化类型( Parameterized Types),则 Signature 属性会为它记录泛型签名信息。
8. SourceFile属性
SourceFile属性结构
可以看到,其长度总是固定的8个字节。
9. 其他属性
Java虚拟机中预定义的属性有20多个,这里就不一一介绍了。
总结