类的生命周期如下
加载->链接(验证+准备+解析)->初始化->使用->卸载
加载过程包含前面的五个阶段
加载->链接(验证+准备+解析)+初始化
加载,验证,准备,初始化,卸载的顺序是确定的,类的加载必须按照这个顺序进行,但是解析阶段不一定,它在某些情况下是可以在初始化之后才开始的,因为java支持运行时绑定.
一.加载:
jvm主要完成三件事
1.通过类的全限定名来获取定义此类的二进制字节流(Class文件),获取方式可以是jar,war,网络中获取,jsp文件生成等方式.
2.将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构,方法区就是用来存放已被加载的类信息,常量,静态变量,即时编译器编译后的代码缓存
3.在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的访问入口.
二.链接
类的加载过程后,在方法区生成了java.lang.Class对象,接着会进入链接阶段,
1.验证:验证被加载的类是否有正确的结构,类数据是否符合虚拟机的要求,确保不会危害虚拟机的安全.
2.准备: 为静态变量在方法区分配内存,并赋默认初始值(0或者null);
3.解析: 将类的二进制数据中的符号引用替换为直接引用;
三.类的初始化
为静态变量赋程序设定的初始值 比如static int a = 100;
在准备阶段这个a会被赋值为0,在初始化阶段被赋值为100;
java虚拟机规范中明确规定了有些只有一下五种情况必须对类进行初始化
1.使用new关键字创建类的实例,或者getstatic,putstatic读取或设置一个静态字段的值.或者调用一个静态方法的时候,对应的类必须进行过初始化;
2.通过java.lang.reflect包的方法对类进行反射调用的时候,如果类没有进行过初始化,则首先他要进行初始化.
3.当初始化一个类的时候,如果发现其父类没有进行过初始化,则首先进行父类的初始化.
4.当虚拟机启动时,用户需要指定一个主类(包含main方法的类) 虚拟机会首先初始化这个类.
5.使用jdk动态语言支持时,如果一个java.lang.invoke.MethodHandle实例最后的解析结果REF_getStatic,REF_putStatic、RE_invokeStatic的方法句柄,并且这个方法句柄对应的类没有进行初始化,则需要先触发其初始化。