java类的声明周期大致分为以下七个部分:
加载(Loading):
加载阶段是“类加载”过程的第一个阶段,在此阶段,虚拟机需要完成以下三件事情:
1.通过一个类的全限定名来获取定义此类的二进制字节流。
2.将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
3.在java堆中生成一个代表这个类的java.lang.Class对象,作为方法区这些数据的访问入口。
验证(Verification):
验证是连接阶段的第一步(连接:验证、准备、解析)
加载和验证是交叉进行的,验证二进制字节流代表的字节码文件是否合格。
(验证阶段对于虚拟机的类加载机制来说,不一定是必要的阶段。如果所运行的全部代码确认是安全的,可以使用-Xverify:none参数来关闭大部分的类验证措施,以缩短虚拟机类加载时间。)
准备(preparation):
准备阶段是为类的静态变量分配内存,然后初始化其值,如果类变量是常量,则直接赋值为该常量值否则为java类型的默认值。这些内存都将在方法区中进行分配。
准备阶段不分配类中的实例变量的内存,实例变量将会在对象实例化时随着对象一起分配在java堆中。
解析(reslution):
指将常量池内的符号引用替换为直接引用的过程。解析可能在初始化前,也可能在初始化后。
符号引用:以一组符号来描述所引用的目标,符号可以是任何形式的字面量,只要使用时能无歧义的定义到目标位置即可。符号引用与虚拟机实现的内存布局无关,引用的目标并不一定已经加载到内存中。
直接引用 : 直接引用可以是直接指向目标的指针、相对偏移量 或是一个能间接定位到目标的句柄,如果有了直接引用,那么引用的目标必定在内存中存在。
初始化(initialization):
这个阶段才真正开始执行java代码,父类和子类静态代码块和设置静态变量的初始值为程序员设定的值。
使用(using):
上述过程完成后类才真正加载完:
接着从main方法开始的第一条语句执行。
在类的实例被创建起,在堆中分配内存,开始初始化实例变量。
接着执行父类的非静态初始化块——>父类构造——>子类非静态初始化块——>子类构造
(类变量从该类的准备阶段起开始存在,直到系统完全销毁这个类,类变量的作用域与这个类的生存范围相同)
(而实例变量则从该类的实例被创建起开始存在,直到系统完全销毁这个实例)
卸载(unloading):
未深入了解。