Class类文件的结构

Class 文件是一组以 8 位字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑地排列在 Class 文件之中,中间没有添加任何分隔符,这使得整个 Class 文件中存储的内容几乎全部是程序运行的必要数据,没有空隙存储。当遇到需要占用 8 位字节以上的空间的数据项时,则会按照高位在前的方式分割成若干个 8 位字节进行存储。

根据 Java 虚拟机规范规定,Class 文件格式采用一种类似 C 语言结构体的伪结构来存储数据,这种伪结构中只有两种数据类型:无符号数和表。

  • 无符号数属于基本的数据类型,以 u1、u2、u4、u8 来分别代表 1 个字节、2 个字节、4 个字节以及 8 个字节的无符号数,无符号数可以用来描述数字、索引引用、数量值或者按照 UTF-8 编码构成的字符串值。
  • 表是有多个无符号数或者其他表作为数据项构成的复合数据类型,所有表都习惯性地以 “_info” 结尾。表用于描述有层次关系的复合结构的数据,整个 Class 文件本质上就是一张表,它是由下表所示的数据项构成。
    Class类文件的结构_第1张图片
    Class文件格式

这里我们必须明确的是,Class 类文件的结构是严格限定的,所以在上表的数据项,无论是顺序还是数量,甚至于数据存储的字节序这样的细节,都是被严格限定的,那个字节代表什么含义,长度是多少,先后顺序如何,都不允许改变。
接下来分析一下 Class 类文件结构的每一个数据项所代表的含义:

  1. magic(魔数):每个 Class 文件的头 4 个字节称为魔数(Magic Number),它的唯一作用是确定这个文件是否为一个能被虚拟机接受的 Class 文件。
  2. minor_version 和 major_version:紧接着魔数的 4 个字节存储的是 Class 文件的版本号,第 5 个和第 6 个字节是次版本号,第 7 和第 8 个字节是主版本号。Java 的版本号是从 45 开始的,JDK 1.1 之后的每个 JDK 大本版发布主版本号向上加 1,高版本的 JDK 能向下兼容以前的版本的 Class 文件。现在到 JDK 1.8 次主版本为:45~52。
  3. constant_pool_count 和 constant_pool 常量池:常量池可以理解为 Class 文件之中的资源仓库,它是 Class 文件结构中与其他项目关联最多的数据类型,也是占用 Class 文件空间最大的数据项目之一,同时它还是在 Class 文件中第一个出现的表类型数据项目。
    常量池中主要存放两大类常量:字面量符号引用 。字面量相当于 Java 语言层面的常量概念,如文本字符串、声明为 final 的常量值。而符号引用则属性编译原理方面的概念,包括了下面的三类常量:
    ①、类和接口的全限定名。
    ②、字段的名称和描述符(包含字段的数据类型)。
    ③、方法的名称和描述符(包含方法的参数列表[包括数量、类型以及顺序]和方法的返回值类型)。
  4. access_flags 访问标志:这个标志用于识别一些类或者接口层次的访问信息,包括:这个 Class 是类还是接口;是否定义为 public 类型;是否定义为 abstract 类型;如果是类的话,是否被声明为 final 等。
  5. this_class(类索引)和 super_class(父类索引)以及 interfaces_count、interfaces(接口索引集合):Class 文件中由这三项数据来确定这个类的继承关系。类索引用于确定这个类的全限定名,父类索引用于确定这个类的父类的全限定名。接口索引就是用来描述这个类实现了哪些接口。
  6. fields_count、fields(字段表集合):字段表用于描述接口或者类中声明的变量。字段包括类级变量以及实例级字段,但不包括方法内部声明的局部变量。
  7. methods_count、methods(方法表集合):方法表用于描述接口或类中的声明的所有方法以及父类的方法。如果父类方法在子类中没有被重写,方法表集合中就不会出现来自父类的方法信息。但同样的,有可能会出现由编译期自动添加的方法,最典型的就是 类构造器 方法实例构造器 方法
  8. attribute_count、attributes(属性表集合):在 Class 文件、字段表、方法表都可以携带自己的属性表集合,以用于描述某些场景专有的信息。

Class 类文件是 Java 代码通过 Java 编译器 编译而成,对于使用 Java 的程序猿,了解一下 Class 类文件的结构是很有必要的。

你可能感兴趣的:(Class类文件的结构)