Class类文件的结构
Class文件是一组以8个字节为基础单位的二进制流,各个数据严格按照顺序紧凑地排列在文件之中,中间没有添加任何分隔符。文件格式采用一宗类似于C语言结构体的伪结构来存储数据,这种伪结构只要两种数据类型:无符号数和表
- 无符号数:属于基本的数据类型,以u1、u2、u4、u8来分别表示一个字节、2个字节、4个字节和8个字节的无符号数。无符号数可以用来描述数字、索引引用、数量值或者按照UTF-8编码构字符串值
- 表:是由多个无符号数或者其他表作为数据项构成的符合数据类型,所有表的命名都以"_info""结尾
魔术(Magic Number)
- 每个Class文件开头的4个字节的无符号整数
- 存在的作用是确定这个文件是一个能被虚拟机接受的有效合法的Class文件
- 魔术值固定为0×CAFEBABE
Class文件版本号
- 第五个和第六个字节代表编译的副版本号
minor_version
,第七个和第八个是编译的主版本号major_version
- 版本号和Java编译器的对应关系
编译器版本 | 主版本 | 副版本 |
---|---|---|
1.7 | 51 | 0 |
1.8 | 52 | 0 |
常量池
- 主要存储:字面量和符号引用
- 是Class文件结构中与其他项目关联最多的数据,也是占用Class文件空间最大的数据项目之一
- 可以使用
javap
命令输出常量表
访问位置
在常量池结束之后,紧接着的2个字节代表访问标志,用于识别一些类或者接口层次的访问信息,包括:
- 这个Class是类还是接口;
- 是否定义了public类型;
- 是否定义为abstract类型;
- 如果是类,是否被声明为final等
类索引、父类索引与接口索引集合
类索引(this_class)和父类索引(super_class)都是一个u2类型的数据,而和接口索引(interfaces)是一组u2类型索引的结合,Class文件通过这三项数据来确定该类型的集成关系
字段表集合
字段表(field_info)用于描述接口或类中声明的变量。变量指类级变量和实例级变量,但不包括在方法内部声明的局部变量。描述字段的信息包括:
- 作用域(public private protected)
- 是实例变量还是类变量(static)
- 可变性(final)
- 并发可见性(volatile)
- 可否被序列化(transient)
- 字段数据类型(基本数据类型、对象和数组)
方法表集合
方法表集合和字段表集合结构类似,不同之处在于volatile和transient不能用于描述方法,所以方法表的访问标识中没有ACC_VOLATILE
和`ACC_TRANSIENT
属性表集合
将如下代码编译之后使用javap
指令查看属性集合内容
public class Test2021 {
public void showMessage() {
System.out.println("Hello World");
}
}
使用java -v Test2021.class
之后就可以看到属性表集合内存存储的数据
{
public Test2021();
descriptor: ()V
// 类作用域
flags: ACC_PUBLIC
// 内部存储字节码指令
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."":()V
4: return
// Java源码行号与字节码指令的对应关系
LineNumberTable:
line 6: 0
// 局部变量表
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this LTest2021;
public void showMessage();
descriptor: ()V
// 方法作用域
flags: ACC_PUBLIC
// 内部存储字节码指令
Code:
stack=2, locals=1, args_size=1
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3 // String Hello World
5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
// Java源码行号与字节码指令的对应关系
LineNumberTable:
line 9: 0
line 10: 8
// 局部变量表
LocalVariableTable:
Start Length Slot Name Signature
0 9 0 this LTest2021;
}
// 源文件名称
SourceFile: "Test2021.java"
最新的《JAVA虚拟机规范-Java SE 8 Edition》中定义了23个属性:各属性代表的实际含义点击这里查看
参考文章
- Java虚拟机之Class类文件结构
- 《深入理解Java虚拟机》(第三版)