jvm学习脉络
class文件格式
- 类和接口不一定定义在文件里,也可以通过类加载器直接生成
- class文件是一组以8位字节为基础单位的二进制流,16位、32位、64位分别通过构造2个、4个、8个连续的8位字节来表示
- 必须严格按顺序存放,不能有间隔
- class文件格式采用一种类似于C语言结构体的伪结构来存储数据,这种伪结构中只有两种数据类型:无符号数和表。
- class文件中的数据要么是单个值,要么是二维表。
- 表的每一项长度不固定
- 可以使用
java.io.DataInput
、java.io.DataInputStream
、java.io.DataOutput
、java.io.DataOutputStream
来访问这种格式的文件
class文件的组织结构
文件结构
- 魔数
唯一作用是确保文件能被虚拟机接受,固定值不变,是oxCAFEBABE
- 本文件的版本信息
主版本号(major_version)和副版本号(minor_version)共同构成了class文件的版本号
常见的jdk1.8的版本就是52.0,就是44+8.0来的
- 常量池
主要保存字符串常量、类名、接口名、
常量池以1~constant_pool_count-1
为索引,第一个字节为类型标记,用于标记格式,称为tagbyte - 访问标志
由标志构成的掩码,用于表示类或者接口的访问权限
- 类索引
必须是常量表的有效索引
CONSTANTS_Class_info结构体 - 父类索引
必须是常量表的有效索引
0或者CONSTANT_Class_info结构体类型 - 接口索引集合
0~interfaces_count - 字段表集合
field_info结构 - 方法表集合
method_info结构 - 属性表集合
attribute_info结构
字段描述符
方法描述符
0个或者多个参数描述符,以及一个返回值描述符。V 表示方法没有返回值。
常量池
常量池的通用结构
CONSTANT_Class_info
数组类型的描述符中描述的数组,维度必须小于255。
CONSTANT_Fieldref_info、CONSTANT_Methodref_info和CONSTANT_InterfaceMethodref_info
CONSTANT_String_info
成员必须是 CONSTANT_Utf8_info 结构
CONSTANT_Integer_info和CONSTANT_Float_info
- Integer采用高位优先存储
- Float按照IEEE 754标准存储
CONSTANT_Long_info和CONSTANT_Double_info
所有的成员都占2个项的空间。备注:历史设计原因。
long的表示
double的表示,同样是IEEE 754标准
CONSTANT_NameAndType_info
tag最大值为CONSTANT_NameAndType(12)
CONSTANT_Utf8_info
tag值为CONSTANT_Utf8(1)
Utf8标注具体规则如下
CONSTANT_MethodHandle_info
tag最大值CONSTANT_MethodHandle(15)
CONSTANT_MethodType_info
tag的最大值为CONSTANT_MethodType(16)
CONSTANT_InvodeDynamic_info
tag的最大值为CONSTANT_InvodeDynamic(18)
字段
每个字段都是 field_info
结构定义的
方法
所有的方法都是由 method_info
结构来定义
属性
ConstantValue属性
Code属性
StackMapTable属性
Exceptions属性
InnerClass属性
EnclosingMethod属性
Synthetic属性
Signature属性
SourceFile属性
SourceDebugExtension
LineNumberTable属性
LocalVariableTable属性
LocalVariableTypeTable属性
Deprecated属性
RuntimeVisiableAnnotations属性
RuntimeInvisiableAnnotation属性
RuntimeVisiableParameterAnnotions属性
RuntimeinvisiableAnnotations属性
RuntimeVisiableTypeAnnotations属性
target_info联合体
type_path机构体
RuntimeInvisiableTypeAnnotayions属性
AnnotationDefault属性
BootstrapMethods属性
MethodParameters属性
格式检查
- 前四个字节必须是正确的魔数
- 所有属性必须符合合适的长度
- class文件的内容不能缺失,尾部也不能有多余的字节
- 常量池必须符合约束
代码约束
静态约束
静态约束确定了虚拟机指令在Code数组中是如何排列的
结构化约束
Code数组上的结构化约束是为了限制Java虚拟机指令直接的关系
文件校验
类型检查验证
- 版本号大于50的必须使用类型检查验证。既jdk版本必须大于jdk1.6