1.加载

加载时类加载第一个阶段,在加载阶段,虚拟机需要完成以下三个阶段:

1)通过一个类的全限定名来获取定义此类的二进制字节流;

2)将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构;

3)在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据结构的访问入口。

加载阶段完成后,虚拟机外部的二进制字节流就按照虚拟机所需的格式存储在方法区中,方法区中的数据存储格式由虚拟机实现自行定义,虚拟机规范未规定此区域的具体数据结构。

2.验证

验证是连接阶段的第一步,目的是为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。

虚拟机如果不检查输入的字节流,对其完全信任的话,很可能会因为载入了有害的字节流而导致系统崩溃,所以验证是虚拟机对自身保护的一项重要工作。

验证阶段大致上会完成下面4个阶段的检验动作:文件格式验证,元数据验证,字节码验证,符号引用验证。

1)文件格式验证

验证字节流是否符合Class文件格式的规范,并且能被当前版本的虚拟机处理。

2)元数据验证

对字节码描述的信息进行语义分析,以保证其描述的信息符合Java语言规范的要求。

3)字节码验证

主要目的是通过数据流和控制流分析,确定程序语义是合法的、符合逻辑的。如果一个类方法体的字节码没有通过字节码验证,那肯定是有问题的;但如果一个方法体通过了字节码验证,也不能说明其一定是安全的。

4)符号引用验证

发生在虚拟机将符号引用转化为直接引用的时候,这个转化动作将在连接的第三阶段--解析阶段发生。符号引用验证可以看作是对类自身以外(常量池中的各种符号引用)的信息进行匹配性校验。

3.准备

正式为类变量分配内存并设置类变量初始值的阶段,这些变量所使用的内存都将在方法区中进行分配。这时候进行内存分配的仅包括类变量(被static修饰的变量),而不包括实例变量。

4.解析

虚拟机将常量池内的符号引用替换为直接引用的过程。解析动作只要针对类或接口、字段、类方法、接口方法、方法类型、方法句柄和调用点限定符7类符号引用进行。

5.初始化

类加载的最后一步,除了在加载阶段用户应用程序可以通过自定义类加载器参与之外,其余动作完全由虚拟机主导和控制。到了初始化阶段,才真正开始执行类中定义的Java程序代码(或者说是字节码)。

对于任意一个类,都需要由加载它的类加载器和这个类本身一同确立其在Java虚拟机中的唯一性,每一个类加载器,都拥有一个独立的类名称空间。这句话可以表达得更通俗一些:比较两个类是否“相等”,只有在这两个类是由同一个类加载器加载的前提下才有意义,否则,即使这两个类来源于同一个Class文件,被同一个虚拟机加载,只要加载它们的类加载器不同,那这两个类就必定不相等。