Skip to content

访问标识/类索引/父类索引/接口索引

Class 文件结构中的索引区域

Class 文件中,访问标识和各类索引决定了类的身份和继承关系。

类索引(this_class)

类索引指向常量池中的一个 CONSTANT_Class 常量,表示当前类:

this_class (u2):

  └──▶ constant_pool[this_class] = CONSTANT_Class_info

                                        └──▶ name_index → CONSTANT_Utf8 = "com/example/User"

父类索引(super_class)

父类索引指向常量池中的一个 CONSTANT_Class 常量,表示父类:

super_class (u2):

  └──▶ constant_pool[super_class] = CONSTANT_Class_info

                                        └──▶ name_index → CONSTANT_Utf8 = "java/lang/Object"

特殊情况

场景super_class 值说明
class User {}指向 java/lang/Object默认继承 Object
class User extends Person {}指向 Person显式指定父类
public interface I {}值为 0接口的父类没有意义
public interface I extends A, B {}值为 0接口也用 0

接口索引集合(interfaces)

接口索引集合存储当前类实现的所有接口:

interfaces_count (u2):

  └── N 个接口索引

interfaces[0] (u2):

  └──▶ constant_pool[interfaces[0]] = CONSTANT_Class_info

                                              └──▶ name_index → CONSTANT_Utf8 = "java/io/Serializable"

查看接口索引

bash
javap -verbose User.class

# 输出:
# public class com.example.User implements java.io.Serializable
#   ...
#   interfaces count: 1
#   public static final transient java.io.Serializable JNI;
#     descriptor: Ljava/io/Serializable;
#   ...

字段表集合(fields)

基本结构

fields_count (u2): 字段数量

fields[]:
  field_info {
    u2  access_flags;       // 访问标识
    u2  name_index;         // 字段名(指向 Utf8)
    u2  descriptor_index;   // 描述符(指向 Utf8)
    u2  attributes_count;    // 属性数量
    attribute_info  attributes[attributes_count];
  }

字段的访问标识

标识说明
ACC_PUBLIC0x0001public
ACC_PRIVATE0x0002private
ACC_PROTECTED0x0004protected
ACC_STATIC0x0008static
ACC_FINAL0x0010final
ACC_VOLATILE0x0040volatile
ACC_TRANSIENT0x0080transient
ACC_SYNTHETIC0x1000编译器生成
ACC_ENUM0x4000枚举字段

字段描述符

字段描述符描述字段的类型:

java
public class User {
    private String name;     // 描述符: Ljava/lang/String;
    private int age;        // 描述符: I
    private boolean active; // 描述符: Z
    private String[] roles; // 描述符: [Ljava/lang/String;
}

查看字段表

bash
javap -verbose User.class

# 输出:
# private java.lang.String name;
#   descriptor: Ljava/lang/String;
#   flags: ACC_PRIVATE
#
# private int age;
#   descriptor: I
#   flags: ACC_PRIVATE

方法表集合(methods)

基本结构

methods_count (u2): 方法数量

methods[]:
  method_info {
    u2  access_flags;       // 访问标识
    u2  name_index;         // 方法名(指向 Utf8)
    u2  descriptor_index;   // 描述符(指向 Utf8)
    u2  attributes_count;    // 属性数量
    attribute_info  attributes[attributes_count];
  }

方法的访问标识

标识说明
ACC_PUBLIC0x0001public
ACC_PRIVATE0x0002private
ACC_PROTECTED0x0004protected
ACC_STATIC0x0008static
ACC_FINAL0x0010final
ACC_SYNCHRONIZED0x0020synchronized
ACC_BRIDGE0x0040编译器生成的桥接方法
ACC_VARARGS0x0080可变参数方法
ACC_NATIVE0x0100native 方法
ACC_ABSTRACT0x0400abstract
ACC_STRICT0x0800strictfp
ACC_SYNTHETIC0x1000编译器生成

方法描述符

java
// 方法描述符示例

String toString()
// → ()Ljava/lang/String;

int indexOf(String str, int fromIndex)
// → (Ljava/lang/String;I)I

void main(String[] args)
// → ([Ljava/lang/String;)V

boolean equals(Object obj)
// → (Ljava/lang/Object;)Z

查看方法表

bash
javap -verbose User.class

# 输出:
# public java.lang.String toString();
#   descriptor: ()Ljava/lang/String;
#   flags: ACC_PUBLIC
#   Code:
#     stack=2, locals=1, args_size=1
#        0: aload_0
#        1: getfield      #2
#        4: areturn

属性表集合(attributes)

重要的预定义属性

JVM 定义了多种预定义属性,其中最重要的是 Code 属性:

属性名说明适用
Code方法的字节码方法表
LineNumberTable行号表Code 属性
LocalVariableTable局部变量表Code 属性
LocalVariableTypeTable泛型局部变量表Code 属性
SourceFile源文件名类/接口
SourceDebugExtension调试扩展类/接口
Deprecated已废弃字段/方法/类
Synthetic编译器生成字段/方法/类
Signature泛型签名类/方法/字段
RuntimeVisibleAnnotations可见注解类/方法/字段

SourceFile 属性

记录源文件名:

bash
javap -verbose User.class | grep SourceFile

# 输出:
# SourceFile: User.java

Deprecated 属性

标记已废弃的类/方法/字段:

java
@Deprecated
public void oldMethod() { }

// 字节码中:
// Deprecated: <no information>

Signature 属性

JDK 5 引入泛型后,泛型信息需要额外存储:

java
public class Container&lt;T&gt; {
    private T value;
}

// Signature: LContainer&lt;TT;&gt;;

本节小结

Class 文件索引结构速查:

字段指向说明
this_classCONSTANT_Class当前类
super_classCONSTANT_Class(值为 0 表示接口)父类
interfaces[]CONSTANT_Class 数组实现的接口
fields[]字段表集合所有字段
methods[]方法表集合所有方法
attributes[]属性表集合附加信息

字段表和方法表的结构类似,都是 access_flags + name + descriptor + attributes。

下一节,我们来看 字段表/方法表/属性表集合

基于 VitePress 构建