本文来自网易云社区
作者:吕宗胜
在JAVA中,有一句口号我们众所周知,“一次编写,到处运行”。而支持JAVA这种特性的关键之处在于JAVA虚拟机和字节码存储格式,JAVA虚拟机不与JAVA变成语言捆绑,只与Class文件所关联。正因为JAVA只与Class文件相关,它不关心Class的来源,所以虚拟机对Class文件的格式有着十分严格的定义,以便进行Class的合法性等的验证。而Class文件需要被JAVA虚拟机加载,才能最终被虚拟机执行。
1.类的生命周期
类从被加载到虚拟机到卸载出内存,它的整个生命周期有:加载、验证、准备、解析、初始化、使用、卸载。其中验证、准备和解析这3个部分统称为连接。
从类加载的原则上来说,类的生命周期一般是按照这个顺序来的,这里我们重点来看看加载、验证、准备、解析和初始化这5个过程,这5个过程是类在使用之前会完成。下面我们重点来介绍一下类不同生命周期的具体过程。
1.1加载
在加载阶段,虚拟机要完成一下3件事情:
a. 获取类定义的二进制流(通过类的全限定名来获取)
b. 将该二进制流所代表的静态存储结构转化为方法区的运行时数据结构
c. 在内存中生成一个代表该类的java.lang.Class对象。
1.2 验证
验证是连接阶段的第一步,这一阶段的目的主要是为了验证Class文件的正确性,JAVA虚拟机对Class文件的来源并没有要求,甚至我们可以用文本编辑器来编写Class文件,所以验证是非常有必要的,验证是否严谨,直接关系虚拟机最终运行的正确性。
验证阶段主要包括对Class文件格式的验证、元数据的验证、字节码的验证以及符号引用的验证。
1.3 准备
准备阶段是开始为类变量进行内存分配并设置变量的初始值。这里说明一下类变量是指被static修饰的变量,而不包含实例变量。这里的类变量的初始化时在方法区中进行内存分配,而不是在堆中进行的。这里说的变量的初始值,是指设置成零值。
public static int value=100; //在类变量初始化的阶段,value的值为0,而不是100
当然,变量被设置成零值,也不是绝对的,如果该类变量是常量的话,则会直接设置成常量值。
1.4 解析
解析阶段是虚拟机将常量池内的符号引用替换成直接引用的过程。
1.5 初始化
类的初始化是类加载过程的最后一步,在准备阶段,类变量已经进行了初始化,而在初始化阶段,虚拟机则会根据程序来初始化类变量和其他资源。
2.类加载器
类加载器是用于实现类的加载动作,在JAVA中,类的唯一性是由类和加载该类的加载器一同唯一决定的。每一个类加载器,都拥有一个独立的类名称空间。所以简单的来说,如果两个类相等,只有在这两个类是由同一个类加载器加载的前提下有成立。
2.1 双亲委派模型