本章详细讲解了Class文件中的各个组成部分,以及每个部分的定义、数据结构和使用方法。以实战的方式演示了Class的数据是如何电存储和访问的。
无关性的基石
- 一次编译,到处运行(跨平台)
- 虚拟机和字节码存储格式
- 不关心Class的来源何种语言。
Class文件的结构
任何一个Class文件都对应着唯一一个类或接口的定义信息,但反过来说,类或接口并不一定都得定义在文件里。Class文件是一组以8位字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑地排列在Class文件中,中间没有任何分隔符。
魔数与Class文件的版本
魔数(0xCAFEBABE):每个Class文件的头4个字节。
作用(基于安全考虑):确定这个文件是否为一个能被虚拟机接受的Class文件。
常量池
可以理解为Class文件中的资源仓库。
位置:主次版本号之后。
存放内容:
- 字面量:接近Java语言层面的常量概念,如:文本字符串、声明为final的常量值等
- 符号引用(编译原理方面的概念):
- 类和接口的全限定名
- 字段的名称和描述符
- 方法的名称和描述符
访问标志
位置:在常量池结束之后。
类索引、父类索引与接口索引
用于描述接口或者类中声明的变量,严格顺序、长度和内容。
作用:通过这三项数据来确定这个类的继承关系。
字段表集合
用于描述接口或者类中声明的变量,严格顺序、长度和内容。
包含内容:作用域、可变性、并发可见性、字段类型等。
方法表集合
与字段表集合一样。
属性表集合
code属性
Exception属性
列举出方法中可能抛出的受检查异常。
LineNumberTable属性(非必需属性)
用于描述Java源码行号和字节行号之间的对应关系。
LocalVariableTable属性(非必需属性)
描述栈中局部变量表中的变量与Java源码中定义的变量之间的关系。
SourceFile属性
记录生成这个Class文件的源码文件名称。
ConstantValue属性(static修饰的变量)
作用:通知虚拟机自动为静态变量赋值。
InnerClass属性
记录内部类与宿主类之间的关联。
Deprecated及Synthetic属性
标志类型的布尔属性,只存在有和没有的区别。
StackMapTable属性
代替原本基于类型推断的字节码验证器,提升字节码验证的性能。
Signature属性
记录泛型签名信息。
BootstrapMethods属性(略)
字节码指令简介
- 字节码与数据类型
- 使用:简化操作记忆,如:i->int等
- 加载和存储指令
- 使用场景:用于将数据在栈帧中的局部变量表和操作数栈之间来回传输
- 运算指令
- 作用:对两个操作数栈上的值进行特定运算。
- 分类:
- 对整型数据进行运算
- 对浮点型数据进行运算
- 类型转换指令
- 作用:将两种不同的数值类型进行相互转换
- 对象创建与访问指令
- 使用场景:虚拟机对实例和数组的创建与操作使用了不同的字节码命令。
- 操作数栈管理指令
- 常用直接操作数栈的指令:pop1、pop2等
- 控制转移指令
- 作用:从指定位置指令继续执行程序
- 方法调用和返回指令(略)
- 异常处理指令
- 虚拟机异常由athrow指令来实现
- 同步指令
- 作用:支持同步和方法内部一段指令序列的同步