Class文件结构

概括

魔数

The magic item supplies the magic number identifying the class file format; it has the value 0xCAFEBABE.

  1. 每个class 文件开头的4个字节的无符号整数称为魔数(Magic Number)
  2. 它的值固定为 0xCAFEBABE
  3. 它的作用是验证这个文件是否是一个能被虚拟机接受的合法的Class文件
  4. 使用魔数是为了安全性考虑,因为文件的扩展名可以改变

版本

minor_version 和major_version的值是此class文件的次要和主要版本号。主要版本号和次要版本号共同确定class文件格式的版本 。如果一个class文件的主要版本号为 M,次要版本号为 m,我们将其class文件格式的版本表示为 Mm。因此,class文件格式版本可以按字典顺序排列,例如,1.5 < 2.0 < 2.1。

当且仅当v位于某个连续范围 Mi.0 ≤ v ≤ Mj.m 中时, Java 虚拟机实现才能支持class版本v的文件格式。该范围基于实现符合的 Java SE 平台的版本。符合给定 Java SE 平台版本的实现必须支持表 4.1-A 中指定的范围 对于那个版本,没有其他范围。

常量池计数器

The value of the constant_pool_count item is equal to the number of entries in the constant_pool table plus one. A constant_pool index is considered valid if it is greater than zero and less than constant_pool_count, with the exception for constants of type long and double noted in §4.4.5.

  1. 因为常量池的数量不确定,所以需要放置两个字节表示常量池容量计数值
  2. 常量池容量计数值从1开始,即 constant_pool_count = 1 表示常量池中有0个常量项

常量池

The constant_pool is a table of structures (§4.4) representing various string constants, class and interface names, field names, and other constants that are referred to within the ClassFile structure and its substructures. The format of each constant_pool table entry is indicated by its first "tag" byte.

The constant_pool table is indexed from 1 to constant_pool_count - 1.

  1. 常量池是一种表结构,以 1 ~ constant_pool_count-1为索引,表明了后面有多少个常量项
  2. 常量池主要存放字面量和符号引用

字面量

文本字符串、声明为 final 的常量值

符号引用

  1. 类和接口的全限定名、字段的名称和描述符、方法的名称和描述符
  2. 全限定名:例如 com/fly/Demo,即把包名的'.'替换为'/', 为了使连续的多个全限定名之间不产生混淆,最后一般会加上一个';'表示全限定名结束
  3. 描述符:用来描述字段(类的属性)数据类型、方法的参数列表和返回值。基本数据类型以及无返回值的 void 类型都用一个大写字符来表示,对象类型用字符 L 加对象的全限定名表示
  4. 用描述符来描述方法时,按照先参数列表,后返回值的顺序描述,参数列表按照参数的严格顺序放在一组小括号“()”之内。如方法java.lang.String toString()的描述符为()Ljava/lang/String
  5. 虚拟机在加载Class文件的时候才会进行动态链接,即把常量池的符号引用在类加载过程中的解析阶段将其替换为直接引用,并翻译到具体的内存地址中

访问标识

The value of the access_flags item is a mask of flags used to denote access permissions to and properties of this class or interface. The interpretation of each flag, when set, is specified in Table 4.1-B.

  1. 用于识别一下类或者接口层次的访问信息


2. 每一种类型的表示都是通过设置访问标记的32位中的特定位来实现的。比如,若是public final的类,则该标记为ACC_PUBLIC | ACC_FINAL
3. 使用ACc_SUPER可以让类更准确地定位到父类的方法super.method() ,现代编译器都会设置并且使用这个标记

类索引

The value of the this_class item must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_Class_info structure (§4.4.1) representing the class or interface defined by this class file.

  1. 类索引用于确定这个类的全限定名
  2. 常量池在这个索引处的成员必须是 CONSTANT_Class_info 类型结构体,该结构体表示这个class文件所定义的类或接口

父类索引

For a class, the value of the super_class item either must be zero or must be a valid index into the constant_pool table. If the value of the super_class item is nonzero, the constant_pool entry at that index must be a CONSTANT_Class_info structure representing the direct superclass of the class defined by this class file. Neither the direct superclass nor any of its superclasses may have the ACC_FINAL flag set in the access_flags item of its ClassFile structure.

If the value of the super_class item is zero, then this class file must represent the class Object, the only class or interface without a direct superclass.

For an interface, the value of the super_class item must always be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_Class_info structure representing the class Object.

  1. 父类索引用于确定这个类的父类的全限定名。由于Java语言不允许多重继承,所以父类索引只有一个,除了java.lang.Object 之外,所有的Java类都有父类,因此除了java.lang.Object 外,所有Java类的父类索引都不为0。
  2. superclass指向的类不能是final

接口计数器

The value of the interfaces_count item gives the number of direct superinterfaces of this class or interface type.

interfaces_count 的值表示当前类或接口的直接超接口数量

接口索引集合

Each value in the interfaces array must be a valid index into the constant_pool table. The constant_pool entry at each value of interfaces[i], where 0 ≤ i < interfaces_count, must be a CONSTANT_Class_info structure representing an interface that is a direct superinterface of this class or interface type, in the left-to-right order given in the source for the type.

  1. 接口索引集合用来描述这个类实现了哪些接口,这些被实现的接口将按 implements 语句(如果这个类本身是一个接口,则应当是 extends语句)后的接口顺序从左到右排列在接口索引集合中
  2. interfaces []中每个成员的值必须是对常量池表中某项的有效索引值,它的长度为 interfaces_count。每个成员interfaces[i]必须为CONSTANT_Class_info结构,其中0《m i 〈 interfaces_count。在 interfaces[]中,各成员所表示的接口顺序和对应的源代码中给定的接口顺序(从左至右)一样,即interfaces[0]对应的是源代码中最左边的接口。

字段计数器

The value of the fields_count item gives the number of field_info structures in the fields table. The field_info structures represent all fields, both class variables and instance variables, declared by this class or interface type.

  1. fields_count的值表示当前class文件fields表的成员个数,用两个字节表示
  2. fields表中每个成员都是一个field_info结构,用于表示该类或接口所声明的所有类字段或者实例字段,不包括方法内部声明的变量,也不包括从父类或父接口继承的那些字段

字段表集合

Each value in the fields table must be a field_info structure (§4.5) giving a complete description of a field in this class or interface. The fields table includes only those fields that are declared by this class or interface. It does not include items representing fields that are inherited from superclasses or superinterfaces.

  1. 用于描述接口或类中声明的变量。字段(field)包括类级变量以及实例级变量,但是不包括方法内部、代码块内部声明的局部变量
  2. 字段叫什么名字、字段被定义为什么数据类型,这些都是无法固定的,只能引用常量池中的常量来描述
  3. 它指向常量池索引集合,它描述了每个字段的完整信息。比如字段的标识符、访问修饰符((public、private或protected)、是类变量还是实例变量(static修饰符)、是否是常量(final修饰符)等
  4. 它不包括父类或实现接口的字段
  5. 每个字段都由一个field_info结构描述。
  6. 一个class文件中的两个字段不得具有相同的名称和描述符

字段表访问标识

  1. 类的每个字段最多可以设置其ACC_PUBLIC、ACC_PRIVATE和ACC_PROTECTED标志之一,并且不得同时设置其ACC_FINAL和ACC_VOLATILE标志
  2. 接口字段必须有自己的ACC_PUBLIC, ACC_STATIC和ACC_FINAL标志设置

字段表名称索引

The value of the name_index item must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_Utf8_info structure which represents a valid unqualified name denoting a field .

根据字段名称索引的值,查询常量值中的指定索引项

字段表描述符索引

The value of the descriptor_index item must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_Utf8_info structure (§4.4.7) which represents a valid field descriptor (§4.3.2).

描述符的作用是用来描述字段的数据类型、方法的参数列表(包括数量、类型以及顺序)和返回值。根据描述符规则,基本数据类型(byte, char , double ,float, int,long, short, boolean)及代表无返回值的void类型都用一个大写字符来表示,而对象则用字符L加对象的全限定名来表示,如下所示:

方法表集合

Each value in the methods table must be a method_info structure giving a complete description of a method in this class or interface. If neither of the ACC_NATIVE and ACC_ABSTRACT flags are set in the access_flags item of a method_info structure, the Java Virtual Machine instructions implementing the method are also supplied.

The method_info structures represent all methods declared by this class or interface type, including instance methods, class methods, instance initialization methods , and any class or interface initialization method . The methods table does not include items representing methods that are inherited from superclasses or superinterfaces.

  1. 指向常量池索引集合,它完整描述了每个方法的签名
  2. 在字节码文件中,每一个method_info项都对应着一个类或者接口中的方法信息。比如方法的访问修饰符(publicprivate或protected),方法的返回值类型以及方法的参数信息等
  3. 一方面,methods表只描述当前类或接口中声明的方法,不包括从父类或父接口继承的方法。另一方面,methods表有可能会出现由编译器自动添加的方法,最典型的便是编译器产生的方法信息(比如:类(接口)初始化方法cclinit>()和实例初始化方法())

属性表集合

Each value of the attributes table must be an attribute_info structure
If the ACC_MODULE flag is set in the access_flags item, then no other flag in the access_flags item may be set

属性表的每个项的值必须是attribute_info结构

属性计数器

The value of the attributes_count item gives the number of attributes in the attributes table of this class

attributes_count的值表示当前class文件属性表的成员个数

posted @ 2021-12-18 22:49  翻蹄亮掌一皮鞋  阅读(136)  评论(0)    收藏  举报