第六章 类文件结构
第六章 类文件结构
实现平台无关性的基础是虚拟机和字节码的存储格式。Java虚拟机不与任何程序语言绑定,只和其Class
文件这种特殊的二进制文件格式关联。
6.1 Class类文件结构
Class文件格式采用类似C结构体的伪结构存储,包含两种数:无符号数和表。
- 无符号数:基本数据类型 , u1,u2,u3,u4表示不同的长度
- 表:多个无符号数或其他的表作为数据相复合成的复合数据类型。习惯info结尾
1 魔数和Class文件版本
- 头4个字节成为魔数。用来确定文件能否被虚拟机加载
- 紧接着4个字节是Class文件版本号,5和6字节是次版本号。7和8是主版本号(大版本+1)。
2 常量池
主次版本之后是常量池入口,
常量池主要存放两大类变量:
- 字面量:类似常量概念,比如字符串和声明为final的常量值。
- 符号引用:属于编译原理的概念
- 被模块导出或开放的包
- 类和接口的全限定名
- 方法的名称和描述符
- 方法句柄、方法类型
- 动态调用点和动态常量
实际上,Java是在虚拟机加载Class文件时才进行动态连接。
虚拟机加载类时,会从常量池中获取对应的符号引用,再在类创建或运行时解析、翻译到具体的内存中。(这部分涉及到虚拟机的类加载机制)
Tips:
-
而常量池中,会存在每种基本类型对应的字面量。这个也就是为什么会存在对应的基本数据类型??
-
Class文件中的方法,字段都需要引用
CONSTANT_UTF_8
型常量描述名称。u2类型能表达的最大是65535。 -
CONSTANT_Class_info 包含tag和name_index ,tag时标志位,index是常量索引,指向哪个常量结构实例。
3 访问标志
常量池之后,紧接着的2个字节代表访问标志。
包括:是类还是接口、是否定义为public类型、是否定义为abstract、具体是类的话,是否被声明为final 等等
4 类索引、父类索引与接口索引集合
类索引和父类索引,都是u2类型的数据库。接口索引集合是u2的集合
5 字段表集合
字段表用于描述接口或者类中声明的变量。 但不包含在方法内声明的局部变量。
方法表,属性表
方法表 包括访问标志,名称索引,描述符索引,属性表集合。(访问标识就包括synchronized,abstract等关键字)
......
6.2 字节码指令
同步指令
JVM支持方法级的同步和方法内部代码块的同步,这两种都是使用管程(Monitor,或者称为锁)来实现的。
方法级同步:
隐式,无需字节码指令控制。实现通过方法表中的ACC_SYNCHRONIZED访问标识了解是否是同步方法。
此时线程执行到这里就会先持有锁,然后再执行方法,执行完成后再释放。
语句块同步:
minitorener
和monitorexit
两条指令支持synchronized关键字的语义。
others: 为了保证在方法异常完成时monitorenter
和monitorexit
指令依然可以正确配对执行,编译器会产生一个异常处理程序,这个声明可以处理所有的异常,其目的就是保证monitorexit
的指令的执行。