虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换、解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制。
1. 类的加载时机
上图中,加载,验证,准备,初始化和卸载这五个阶段的顺序是确定的,而解析阶段则不一定,可以在初始化之前,也可以在初始化之后,这是为了支持运行时绑定。
接口与类初始化过程的不同点:当一个类在初始化时,要求其父类 全部都已经初始化,但一个接口并不要求其父接口全部都初始化,只有在真正使用到父接口的时候才会初始化。
2. 类加载的过程
1. 加载:在加载过程中虚拟机需要完成以下三件事:
1)通过一个类的全限定名来获取定义此类的二进制字节流;
2)将这个字节流所代表的静态存储结构转换为方法区的运行时数据结构;
3)在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口;
2. 验证:连接阶段的第一步,为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。包括以下验证:
1)文件格式的验证:魔数版本号之类的
2)元数据的验证:验证类与父类之间的关系,对类的元数据进行语义校验
3)字节码验证:最复杂的阶段,通过数据流和控制流分析,确定程序语义是合法的,符合逻辑的,对类的方法体进行校验分析。
4)符号引用验证:对类自身以外(常量池中的各种符号引用)的信息进行匹配性校验,主要发生在虚拟机将符号引用转化为直接引用的时候。
3. 准备:正式为类变量分配内存并设置类变量初始值的阶段,都将在方法区进行分配,只包括类变量,不包括实例变量,而这里说的初始值通常情况下,是数据类型的零值。如果类字段的字段属性表中存在ConstantValue属性(即是final的),就被会初始化为指定的值。
4. 解析:解析阶段是虚拟机将虚拟机常量池的符号引用替换为直接引用的过程。包括以下几种情况:
1)类或接口的解析
2)字段解析
3)类方法解析
4)接口方法解析
5. 初始化:此阶段才真正开始执行类中定义的Java程序代码(或者说是字节码)