最近在看周志明的《深入理解JVM虚拟机》,看到class文件结构,便想边看边做些笔记。我们都知道Java“一次编译,到处运行”的特性,那么这种特性怎么实现的呢?Java源文件被Java编译器编译成JVM可以识别的.class文件执行,即JVM是Java程序运行的底层环境,而JVM虚拟机与操作系统没有什么关系,这就是“一次编译,到处运行”的原因。
但是JVM是怎么执行我们的.class文件的呢?JVM只负责执行.class文件,换言之如果其它语言经编译为.class文件,我们的JVM也是可以执行,其实当前已经有一些语言可以在JVM上执行,如JRuby、Groovy等。所以JVM即有跨平台又有跨语言的特性。
class字节码文件由无符号数和表组成:
- 无符号数:基本数据类型(如u1、u2、u4、u8代表对应数量的字节的无符号数),可以用来描述数字、索引引用、数量值或字符串值。
- 表:多个无符号数的集合。(结尾带_info的一般为表)
Class文件格式:
类型 | 名称 | 数量 | 描述 |
---|---|---|---|
u4 | magic | 1 | 魔数:0xCAFEBABE,用来确定这是一个class文件 |
u2 | minor_version | 1 | Java的次版本号 |
u2 | major_version | 1 | Java的主版本号,高版本可以兼容低版本,低版本不能兼容高版本,如JDK1.7的版本号最大值是51 |
u2 | constant_pool_count | 1 | 常量池容量计数值,唯一的计数从1开始的容量计数 |
cp_info | constant_pool | constant_pool_count-1 | 常量池:主要放字面量(Literal)和符号引用(Symbolic References)。符号引用:类和接口的全限定名(Fully Qualified Name), 字段的名称和描述符(Descriptor),方法的名称和描述符 |
u2 | access_flags | 1 | 访问标志,用于识别一些类或者接口层次的访问信息。为类还是接口、是否为public类型、是否定义为static等 |
u2 | this_class | 1 | 类索引 |
u2 | super_class | 1 | 父类索引,只有一个u2,Java单一继承的体现 |
u2 | interfaces_count | 1 | 接口索引计数值,Java接口多实现的表现 |
u2 | interfaces | interfaces_count | 接口索引 |
u2 | fields_count | 1 | 字段表计数值 |
field_info | fields | fields_count | 字段表:用于描述接口或者类中声明的变量 |
u2 | methods_count | 1 | 方法表计数值 |
method_info | methods | methods_count | 方法表:记录方法的访问标志(access_flags)、名称索引(name_index)、描述符索引(descriptor)、属性表集合(attributes) |
u2 | attributes_count | 1 | 属性表计数值 |
attribute_info | attributes | attributes_count | 属性表:在class文件、字段表、方法表都可以携带自己的属性表集合,用于描述某些场景专有的信息 |
方法表的access_flags(注意其中的):
JVM通过字节码指令去执行class类文件,JVM的指令有:
加载和存储指令、运算指令、类型转换指令、对象创建与访问指令、操作数栈管理指令、控制转移指令、方法调用和返回指令、异常处理指令、同步指令。
无疑与Synchronized相关的就是同步指令了:
Synchronized可以修饰方法和代码块,也可以修饰静态方法和Class。这两种实现都使用了管程Monitor,JVM会给所有class文件的对象和类加一个Monitor。
方法级的同步是隐式的,无需通过字节码指令来控制。这个意思就是只要在方法前加了Synchronized来修饰,就会在方法表的访问标志(access_flags)的SYN_CHRONIZED标志位置为0x0020。当调用该方法时,调用指令会先检SYN_CHRONIZED,如果标志了执行线程首先会看是否有其它线程执有该对象管程Monitor,如果有(Monitor>0)就阻塞等待知道其它线程执行完方法释放管程(Monitor=0),然后才能去持有该对象的管程(Monitor++)。
代码块的同步是通过字节码指令monitorenter和monitorexit来实现的,正确的实现需要Javac编译器和Java虚拟机共同协作支持。