Java虚拟机(三)Class文件结构

class 文件简介

class 文件是javac编译器编译后生成的二进制文件,全部是连续的0/1。可以把 class 文件中的内容分为两种类型:

  1. 无符号数:表示class文件中的值,没有符号,但有长度。u1、u2、u4、u8 (u1表示1字节的无符号数)
  2. :无符号数要么单独存在,要么多个组合成为二维表。

总而言之,class文件中的数据要么是单个值,要么是二维表。


class 文件的组织结构一览

  1. 魔数
  2. 本文件的版本信息
  3. 常量池
  4. 访问标志
  5. 类索引
  6. 父类索引
  7. 接口索引集合
  8. 字段表集合
  9. 方法表集合

魔数

class文件的头4个字节,具体的值是16进制表示的“CAFEBABE”。

魔数的作用就相当于文件后缀名,只不过后缀名容易被修改,不安全,因此在class文件中标示文件类型比较合适。


版本信息

紧接着魔数的4个字节是版本号。它表示本class中使用的是哪个版本的JDK。

在高版本的JVM上能够运行低版本的class文件,但在低版本的JVM上无法运行高版本的class文件,即使该class文件中没有用到任何高版本JDK的特性也无法运行!


常量池

常量池存放两种类型的常量:

  • 字面值常量:字面值常量即我们在程序中定义的被final修饰的值。
  • 符号引用:符号引用就是我们定义的各种名字。包括:类和接口的全限定名、字段的名字和描述符、方法的名字和描述符。

常量池的大小是不固定的,因此常量池开头放置一个u2类型的无符号数,用来存储当前常量池的容量。JVM根据这个值就知道常量池的头尾。(注意:这个值是从1开始的,若为5表示池中有4个常量。)


访问标志

在常量池之后是2字节。

访问标志是用来表示这个class文件是类还是接口、是否被public修饰、是否被abstract修饰、是否被final修饰等。

由于这些标志都由是/否表示,因此可以用0/1表示。

访问标志为2字节,可以表示16位标志,但JVM目前只定义了8种,未定义的直接写0。


类索引、父类索引、接口索引集合

表示当前class文件所表示类的名字、父类名字、接口们的名字。

由于一个类的接口可能有好多个,因此需要用一个集合来表示接口索引,它在类索引和父类索引之后。


字段表集合

存储本类所涉及到的成员变量,包括实例变量和类变量,但不包括方法中的局部变量

每一个字段表只表示一个成员变量,本类中所有的成员变量构成了字段表集合。


方法表集合

所有的方法以二维表的形式存储,每张表来表示一个函数,一个类中的所有方法构成方法表的集合。