[JVM知识汇总-1]JVM内存模型[JVM知识汇总-2]HotSpot虚拟机对象[JVM知识汇总-3]垃圾收集策略与算法[JVM知识汇总-4]HotSpot垃圾收集器【JVM知识汇总-5】内存分配与回收策略【JVM知识汇总-6】JVM性能调优【JVM知识汇总-7】Class文件结构【JVM知识汇总-8】类【JVM知识汇总】-9]类加载的过程[JVM知识总结-10]一个类加载器类的生命周期是从加载到虚拟机到卸载内存开始的。其整个生命周期包括以下7个阶段:加载验证、准备、分析、初始化、使用、卸载验证、准备、分析。这三个阶段统称为连接。加载、验证、准备、初始化、卸载五个阶段的顺序是确定的,类的加载过程必须按照这个顺序一步步开始(注意是“开始”,不是“继续”或者“完成”),并且解析阶段不一定:在某些情况下它可以在初始化之后开始,以支持Java语言的运行时绑定。类加载过程中“初始化”的时机JavaVirtualMachineSpecification并没有强制要求类加载过程的第一阶段(即:loading)何时开始,但是对于“初始化”阶段有严格的规定。必须立即“初始化”类的情况只有5种:当遇到new、putstatic、getstatic、invokestatic字节码指令时,如果类还没有初始化,需要先触发它的初始化。在对类进行反射调用时,如果该类还没有初始化,则需要先触发它的初始化。在初始化一个类的时候,如果它的父类还没有初始化,那么需要先初始化父类。虚拟机启动时,用户需要指定一个包含main()方法的主类,虚拟机首先初始化主类。在使用JDK1.7的动态语言支持时,如果一个java.lang.invoke.Methodhandle实例的最终解析结果是REF_getStatic、REF_putStatic、REF_invokeStatic的方法句柄,并且方法句柄对应的类还没有初始化,你需要先触发它的初始化。这5种场景中的行为称为对类的主动引用。此外,所有其他引用方法都不会触发初始化,称为被动引用。/***被动引用Demo1:*通过子类引用父类的静态字段不会导致子类初始化。**@authorylb**/classSuperClass{static{System.out.println("SuperClassinit!");}publicstaticintvalue=123;}classSubClassextendsSuperClass{static{System.out.println("SubClassinit!");}}publicclassNotInitialization{publicstaticvoidmain(String[]args){System.out.println(SubClass.value);//超类初始化!}}对于静态字段,只有直接定义该字段的类才会被初始化,所以通过子类引用父类中定义的静态字段只会触发父类的初始化,不会触发子类的初始化。/***被动引用Demo2:*通过数组定义来引用类,不会触发该类的初始化。**@authorylb**/publicclassNotInitialization{publicstaticvoidmain(String[]args){SuperClass[]superClasses=newSuperClass[10];}}这段代码不会触发父类的初始化,它是由虚拟机自动生成的,直接继承自java.lang.Object,创建动作由字节码newarry触发。/***被动引用Demo3:*常量会在编译阶段存储在调用类的常量池中。本质上没有直接引用定义常量的类,所以不会触发定义常量的类的初始化。**@authorylb**/classConstClass{static{System.out.println("ConstClassinit!");}publicstaticfinalStringHELLO_BINGO="HelloBingo";}publicclassNotInitialization{publicstaticvoidmain(String[]args){System.out.println(ConstClass.HELLO_BINGO);}}编译通过后,常量存放在NotInittailization类的常量池中。NotInitialization的Class文件中没有ConstClass类的符号引用入口。这两个类在编译成Class之后,没有任何联系。接口加载过程接口加载过程与类加载过程略有不同。初始化一个类时,要求其所有父类都已初始化,而初始化一个接口时,则不要求其所有父接口都已初始化。它会在真正使用父类接口的时候进行初始化。
