Java虚拟机(三)Class文件结构
855字约3分钟
Java
2018-08-09
class 文件简介
class 文件是javac编译器编译后生成的二进制文件,全部是连续的0/1。可以把 class 文件中的内容分为两种类型:
- 无符号数:表示class文件中的值,没有符号,但有长度。u1、u2、u4、u8 (u1表示1字节的无符号数)
- 表:无符号数要么单独存在,要么多个组合成为二维表。
总而言之,class文件中的数据要么是单个值,要么是二维表。
class 文件的组织结构一览
- 魔数
- 本文件的版本信息
- 常量池
- 访问标志
- 类索引
- 父类索引
- 接口索引集合
- 字段表集合
- 方法表集合
魔数
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文件所表示类的名字、父类名字、接口们的名字。
由于一个类的接口可能有好多个,因此需要用一个集合来表示接口索引,它在类索引和父类索引之后。
字段表集合
存储本类所涉及到的成员变量,包括实例变量和类变量,但不包括方法中的局部变量。
每一个字段表只表示一个成员变量,本类中所有的成员变量构成了字段表集合。
方法表集合
所有的方法以二维表的形式存储,每张表来表示一个函数,一个类中的所有方法构成方法表的集合。