如下图所示,JVM类加载机制分为五个部门:加载,验证,筹备,理会,初始化,下面我们就别离来看一下这五个进程。
加载
加载是类加载进程中的一个阶段,这个阶段会在内存中生成一个代表这个类的java.lang.Class工具,软件开发,作为要领区这个类的各类数据的进口。留意这里不必然非得要从一个Class文件获取,这里既可以从ZIP包中读取(好比从jar包和war包中读取),也可以在运行时计较生成(动态署理),也可以由其它文件生成(好比将JSP文件转换成对应的Class类)。
验证
这一阶段的主要目标是为了确保Class文件的字节约中包括的信息是否切合当前虚拟机的要求,而且不会危害虚拟机自身的安详。
筹备
筹备阶段是正式为类变量分派内存并配置类变量的初始值阶段,即在要领区中分派这些变量所利用的内存空间。留意这里所说的初始值观念,好比一个类变量界说为:
public static int v = 8080;
实际上变量v在筹备阶段事后的初始值为0而不是8080,将v赋值为8080的putstatic指令是措施被编译后,存放于类结构器<client>要领之中,这里我们后头会表明。
可是留意假如声明为:
public static final int v = 8080;
在编译阶段会为v生成ConstantValue属性,在筹备阶段虚拟时机按照ConstantValue属性将v赋值为8080。
理会
理会阶段是指虚拟机将常量池中的标记引用替换为直接引用的进程。标记引用就是class文件中的:
等范例的常量。
下面我们表明一下标记引用和直接引用的观念:
初始化
初始化阶段是类加载最后一个阶段,前面的类加载阶段之后,除了在加载阶段可以自界说类加载器以外,其它操纵都由JVM主导。到了初始阶段,才开始真正执行类中界说的Java措施代码。
初始化阶段是执行类结构器<client>要领的进程。<client>要领是由编译器自动收集类中的类变量的赋值操纵和静态语句块中的语句归并而成的。虚拟时机担保<client>要领执行之前,父类的<client>要领已经执行完毕。p.s: 假如一个类中没有对静态变量赋值也没有静态语句块,那么编译器可以不为这个类生成<client>()要领。
留意以下几种环境不会执行类初始化:
类加载器
虚拟机设计团队把加载行动放到JVM外部实现,以便让应用措施抉择如何获取所需的类,JVM提供了3种类加载器:
JVM通过双亲委派模子举办类的加载,虽然我们也可以通过担任java.lang.ClassLoader实现自界说的类加载器。
当一个类加载器收到类加载任务,会先交给其父类加载器去完成,因此最终加载任务城市通报到顶层的启动类加载器,只有当父类加载器无法完成加载任务时,才会实验执行加载任务。