一:类加载的时机
类从被加载到虚拟机内存中开始,到卸载出内存为止,类加载的生命周期图如下:
2.虚拟机规范中要求5中情况必须立即进行“初始化”
1). 遇到new、getstatic、putstatic 或invokestatic 这4条字节码指令的时,如果类没有进行过初始化,则需要初始化。(通常见的场景是:使用new关键字实例化对象的时候、读取或设置一个类的静态字段(除了final修饰、已在编译期把结果放入常量池)、以及调用一个类的静态方法的时候)。
2).使用java.lang.reflect 包的方法对类进行反射调用的时候,如果没有进行过初始化,则需要先触发其初始化。3).当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先出发其父类的初始化。
4). 当虚拟机启动时,用户需要指定一个要执行的主类,虚拟机会先初始化这个主类。
5). JDK 1.7 的动态语言支持,如果一个java.lang.invoke.MethodHandled实例最后的解析结果REF_getStatic、REF_putStatic、REF_invokeStatic的方法句柄,并且这个方法没有进行过初始化,则需要触发先触发其初始化
二:类加载的过程
类加载过程如下:加载、验证、准备、解析和初始化。
1.加载,类加载过程一个阶段需要经历三个阶段
1)通过一个类的全名来获取定义此类的二进制流。
2)将这个字节流所代表的静态存储结构转化为方法区的运行时的数据结构。
3)在内存中生成一个代表这个类的java.lang.Class对象,作为方法区的访问入口。
2.验证过程
1)文件格式验证
第一个阶段验证字节流是否符合class文件格式规范,并且能被当虚拟机处理。
2)元数据验证
第二阶段是对字节码描述的信息进行语义分析,以保证其描述的信息符合java语言规范的要求。
3)字节码验证
第三阶段是整个验证过程中最为复杂的一个阶段,主要目的是通过数据流和控制刘分析,确定程序语义是否合法、符合逻辑。在第二阶段对元数据信息中的数据类型做完校验以后,这个阶段将要对类的方法体进行分析校验,保证校验类的方法在运行是不会做出危害虚拟机的安全事件。
4)符号引用验证
最后一个阶段的校验发生在虚拟机将符号引用转化为直接引用的时候,这个转化动作将在链接的第三阶段---解析阶段中发生。符号引用验证可以看作是对类自身意外的信息进行匹配性校验。
3. 准备
准备阶段会为类变量分配内存并设置类变量的初始值(并不包括赋值),这些变量所使用的内存空间都在方法区中分配。
4.解析
解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程。
符号引用: 是用一种符号来描述所引用的目标,符号可以是任何形式的字面量形式,只要能在使用的时候能无歧义的定位到目标。
直接引用:是直接指向目标指针,相对偏移量或是一个能简介定位到目标的句柄。直接引用是和虚拟机实现内存布局相关的,同一个符号引用在不同的虚拟机实例上直接翻译出来的直接引用一般不同。