当java class文件被编译为标准的二进制class类型之后,这个二进制的类型数据被导入到java虚拟机时,进行了一系列的操作。
1、装载
把二进制形式的java类型读入到java虚拟机中,装载阶段又有三个必须的步骤:
1.1 通过该类型的完全限定名,产生一个代表该数据的二进制数据流。该数据流可能遵守java class文件格式,也可能遵守其它的格式。因为所有的java虚拟机实现必须能识别Java class文件格式,但是个别的实现也可以识别其它的二进制格式。
1.2 解析这个二进制数据流为方法区内的内部数据结构。
1.3 创建一个表示该类型的java.lang.Class类的实例。
有了类型的二进制数据之后,java虚拟机必须对这些数据进行足够的处理,然后才能创建类java.lang.Class的实例对象。因此虚拟机必须把这些二进制数据解析为与实现相关的内部数据结构。
装载步骤的最终产品就是这个class类的实例对象,它成为java程序与内部数据结构之间的接口。
2、连接
该过程分为三个步骤:
2.1 验证
确认类型符合java语言的语义,并且它不会危及虚拟机的完整性。例如:
a.检查final的类不能拥有子类。
b.检查final的方法不会被覆盖。
c.确保在类型和超类型之间没有不兼容的方法声明。
d.检查所有的常量池入口相互之间一致
e.检查常量池中的所有特殊字符串是否符合格式。
f.检查字节码的完整性。
2.2 准备
java虚拟机装载一个类和它的父类,并执行了一些选择性的验证之后,就到了验证阶段。
该阶段主要是java虚拟机为类变量分配内存,设置默认初始值,在初始化之前,类变量都没有被初始化为真正的初始值,因为在准备阶段是不会执行java代码的。在该阶段,虚拟机把给类变量新分配的内存根据类型设置为默认值,也可能为一些数据结构分配内存,这样做,有效地提高了程序运行的性能。
2.3 解析
解析过程就是在类型的常量池中寻找类、接口、字段和方法的符号引用,并把这些符号引用替换成直接引用的过程。这个步骤是可选的,也可能在初始化的时候进行。
3、初始化
该步骤为类变量赋予正确的初始值,也就是程序员希望这个类变量所具备的起始值。在java代码中,一个正确的初始值是通过类变量初始化语句或者静态初始化语句给出的。
初始化一个类包含两个步骤:
a.如果类存在直接超类的话,超类还没有被初始化,就先初始化超类。
b.如果类存在一个类初始化方法,就执行此方法。