【JVM】Class 类文件的结构 1/2

436 阅读3分钟

Class 文件格式采用一种类似于 C 语言结构体的伪结构来存储数据,这种微结构中只有两个数据类型:

  • “无符号数”:以 u1、u2、u4、u8 分别表示 1 个字节、2个字节、4个字节和8个字节的无符号数,无符号数可以用来描述数字、索引饮用、数量值或者按照 UTF-8 编码构成字符串值
  • “表”:由多个无符号数或者其他表作为数据项构成的复合数据类型。

1. 魔数(Magic Number)

位置为第 1-4 个字节,每个 Class 文件的头 4 个字节被称为魔数(Magic Number),它的唯一作用是确定这个文件是否为一个能被虚拟机接受的 Class 文件。魔数=0xCAFEBABE

2. 次版本号(Minor Version)

位置为第 5-6 个字节

3. 主版本号(Major Version)

位置为第 7-8 个字节,Java的版本号是从45开始的,JDK 1.1之后 的每个JDK大版本发布主版本号向上加1(JDK 1.01.1使用了45.045.3的版本号) 高版本的 JDK 能向下兼容以前版本的 Class 文件,但不能运行以后版本的 Class 文件,因为虚拟机会拒绝执行超过其版本号的 Class 文件。

4. 常量池

常量池中主要存放两大类常量

  • 字面量(Literal),接近 Java 语言的常量概念,如文本字符串、被声明为 final 的常量值
  • 符号引用(Symbolic References),接近编译原理方面的概念,主要包括以下几类常量:
    • 被模块导出或者开放的包(Package)
    • 类和接口的全限定名(Fully Qualified Name)
    • 字段的名称描述符(Descriptor)
    • 方法的名称和描述符
    • 方法句柄和方法类型(Method Handle、Method Type、Invoke Dynamic)
    • 动态调用点和动态常量(Dynamically-Computed Call Site、Dynamically-Computed Constant) 常量池特点:
  • 表类型
  • 常量池中常量的数量不固定,所以常量池的入口放置了一项 u2 类型的数据,代表常量池容量计数器(constant_pool_count),这个容量计数从 1 开始。 Class 文件结构中只有常量池的容量计数是从 1 开始,其他集合如:接口索引集合、字段表集合、方法表集合等的容量计数都从 0 开始。

5. 访问标志(access_flags)

占用 2 个字节,用于识别一些类或者接口层次的访问信息,如:这个 Class 是类还是接口、是否定义为 public 类型、是否定义为 abstract 类型等。

6. 类索引、父类索引与接口索引集合

  • 类索引(this_class):一个 u2 类型的数据
  • 父类索引(super_class):一个 u2 类型的数据
  • 接口索引集合(interfaces):一组 u2 类型的数据的集合

7. 字段表集合(field_info)

用于描述接口或者类中声明的变量。

8. 方法表集合

属性表集合(attribute_info):Class 文件、字段表、方法表都可以携带自己的属性表集合,以描述某些场景专有的信息