虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验,转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制。
类加载的时机
类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载,验证,准备,解析,初始化,使用和卸载7个阶段。其中验证,准备,解析3个部分统称为连接,这7个阶段的发生顺序如下图所示。
类的生命周期
加载,验证,准备,初始化和卸载这5个阶段的顺序是确定的,类的加载过
对于这5种会触发类进行初始化的场景,虚拟机规范中使用了一个很强烈的限定语:”有且只有,这5种场景中的行为称为对一个类进行主动引用。除此之外,所有引用类的方式都不会触发初始化,称为被动引用。
被动引用举例
1.通过子类引用父类的静态字段,不会导致子类初始化。
2.通过数组定义来引用类,不会触发此类的初始化
3.常量在编译阶段会存入调用类的常量池中,本质上并没有直接引用到定义常量的类,因此不会触发定义常量的类的初始化。
当一个类在初始化时,要求其父类全部都已经初始化过了,但是一个接口在初始化时,并不要求其父接口全部都完成了初始化,只有在真正使用到父接口的时候(如引用接口中定义的常量)才会初始化。
类加载的过程
接下来说下Java虚拟机中类加载的全过程,也就是加载,验证,准备,解析和初始化这5个阶段所执行的具体动作。
加载
1.如果数组的组件类型(Component Type,指的是数组去掉一个维度的类型)是引用类型,那就递归采用前文定义的加载过程去加载这个组件类型,数组C将在加载该组件类型的类加载器的类名称空间上被标识。
2.如果数组的组件类型不是引用类型(例如int[] 数组),Java虚拟机将会把数组C标记为与引导类加载器关联。
3.数组类的可见性与它的组件类型的可见性一致,如果组件类型不是引用类型,那数组类的可见性将默认为public.
验证
准备
解析
解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程,在Class文件中它以CONSTANT_Class_info,CONSTANT_Fieldref_info,CONSTANT_Methodref_info等类型的常量出现,那解析阶段中所说的直接引用与符号引用又有什么关联呢?
初始化
类加载器
类与类加载器
双亲委派模型
破坏双亲委派模型