1.装载流程图
class文件的装载流程如图所示。
2.类装载的条件
首先我们要搞清楚,class只有在必须要使用时才会被装载。Java虚拟机规定,一个类或接口在初次使用前,必须要进行初始化。这里指的“使用”,是指主动使用,主动使用只有下列几种情况:
· 当创建一个类的实例时,比如使用new关键字,或者通过反射,克隆,反序列化
· 当调用类的静态方法,即当使用了字节码 invokestatic 指令
· 当使用类或接口的静态字段时(final常量除外),比如,使用 getstatic 或者 putstatic 指令
· 当使用 java.lang.refect 包中的方法反射类的方法时
· 当初始化子类时,要求先初始化父类
· 作为启动虚拟机,含有main()方法的那个类
3.流程分析
3.1 加载类
加载类处于类装载的第一个阶段。在加载类时,java虚拟机必须完成以下工作:
· 通过类的全名,获取类的二进制数据流
· 解析类的二进制数据流为方法区内的数据结构
· 创建java.lang.Class 类的实例,表示该类型
对于类的二进制流数据,虚拟机可以通过多种途径产生和获得。最一般地是通过文件系统读入一个class文件。在获取类的二进制信息后,Java虚拟机就会处理这些数据,并最终转化为一个java.lang.Class的实例,java.lang.Class实例是访问类型元数据的接口,也是实现反射的关键数据。通过class类提供的接口,可以访问一个类的方法,字段等信息。
3.2 连接
连接可以分为三个步骤:验证,准备,解析。
3.2.1 验证类
当类加载到系统后,就开始连接操作,验证是连接操作的第一步。大体上Java虚拟机需要做以下的检查:
检查的内容如图所示,比较详细,我就不一一说明了。
3.2.2 准备
当一个类验证通过时,虚拟机就会进入准备阶段。在这个阶段,虚拟机就会为这个类分配相应的内存空间,并设置初始值。
如果类中存在常量字段,那么常量字段也会在准备阶段被附上正确的值,这个赋值属于Java虚拟机的行为,属于变量的初始化。在这个阶段,不会有任何Java代码被执行。
3.2.3 解析类
在准备阶段完成后,就进入到了解析阶段。解析阶段的工作就是将类、接口、字段和方法的符号引用转为直接引用。
Java虚拟机为每个类都准备了一张方法表,将其所有的方法都列在表中,当需要调用一个类的方法的时候,只要知道这个方法在方法表中的偏移量就可以直接调用该方法。通过解析操作,符号引用就可以转变为目标方法在类中方法表中的位置,从而使得方法被成功调用。这就是解析阶段的工作,将类、接口、字段和方法的符号引用转为直接引用。
3.3 初始化
类的初始化是类装载的最后一个阶段。此时,类才会开始执行Java字节码。主要工作是执行类的初始化方法