属性表集合

90 阅读4分钟

方法表集合之后的属性表集合,指的是class文件所携带的辅助信息,比如该 class 文件的源文件的名称。以及任何带有RetentionPolicy.CLASS 或者RetentionPolicy.RUNTIME的注解。这类信息通常被用于Java虚拟机的验证和运行,以及Java程序的调试,一般无须深入了解

此外,字段表、方法表都可以有自己的属性表。用于描述某些场景专有的信息。

属性表集合的限制没有那么严格,不再要求各个属性表具有严格的顺序,并且只要不与已有的属性名重复,任何人实现的编译器都可以向属性表中写入自己定义的属性信息,但Java虚拟机运行时会忽略掉它不认识的属性。

1、attributes_count (属性计数器)

attributes_count的值表示当前class文件属性表的成员个数。属性表中每一项都是一个attribute_info结构。

2 attributes [](属性表)

属性表的每个项的值必须是attribute_info结构。属性表的结构比较灵活,各种不同的属性只要满足以下结构即可。

2.1 属性的通用格式

属性表1.png

即只需说明属性的名称以及占用位数的长度即可,属性表具体的结构可以去自定义。

2.2 属性类型 属性表实际上可以有很多类型,上面看到的Code属性只是其中一种,Java8里面定义了23种属性。 下面这些是虚拟机中预定义的属性: 属性表2.png 属性表3.png 属性表4.png 或(查看官网) 属性表5.png

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属性表的结构,如下图:

属性表6.png 可以看到: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属性表结构:

属性表7.png

6. LocalVariableTable 属性

LocalVariableTable 是可选变长属性,位于 Code属性的属性表中。它被调试器用于确定方法在执行过程中局部变量的信息。 在 Code 属性的属性表中,LocalVariableTable 属性可以按照任意顺序出现。 Code 属性中的每个局部变量最多只能有一个 LocalVariableTable 属性。

  • start pc + length表示这个变量在字节码中的生命周期起始和结束的偏移位置(this生命周期从头0到结尾)
  • index就是这个变量在局部变量表中的槽位(槽位可复用)
  • name就是变量名称
  • Descriptor表示局部变量类型描述 LocalVariableTable 属性表结构: 属性表8.png 7. Signature 属性

Signature 属性是可选的定长属性,位于 ClassFile, field_info 或 method_info结构的属性表中。在 Java 语言中,任何类、 接口、 初始化方法或成员的泛型签名如果包含了类型变量( Type Variables) 或参数化类型( Parameterized Types),则 Signature 属性会为它记录泛型签名信息。

8. SourceFile属性

SourceFile属性结构 属性表9.png 可以看到,其长度总是固定的8个字节。

9. 其他属性

Java虚拟机中预定义的属性有20多个,这里就不一一介绍了。

总结

属性表10.png