类的生命周期是从被加载到虚拟机内存中开始,到卸载出内存结束。过程共有七个阶段,其中到初始化之前的都是属于类加载的部分:加载----验证----准备----解析-----初始化----使用-----卸载,其中,验证、准备、解析这三个阶段也叫连接过程。
1、加载阶段
1)通过一个类的全限定名来获取定义此类的二进制字节流。
2)将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
3)在java堆中生成一个代表这个类的Class对象,作为访问方法区中这些数据的入口。
2.验证
是否有正确的内部结构,并和其他类协调一致
3、准备阶段
这个阶段正式为类变量(被static修饰的变量)分配内存并设置类变量初始值,这个内存分配是发生在方法区中。
1、注意这里并没有对实例变量进行内存分配,实例变量将会在对象实例化时随着对象一起分配在JAVA堆中。
2、这里设置的初始值,通常是指数据类型的零值。
比如:
private static int a = 3;
这个类变量a在准备阶段后的值是0,将3赋值给变量a是发生在初始化阶段。
4、解析
将类的二进制数据中的符号引用替换为直接引用
5、初始化阶段
初始化是类加载机制的最后一步,这个时候才正真开始执行类中定义的JAVA程序代码。在前面准备阶段,类变量已经赋过一次系统要求的初始值,在初始化阶段最重要的事情就是对类变量进行初始化,关注的重点是父子类之间各类资源初始化的顺序。
java类中对类变量指定初始值有两种方式:
1、声明类变量时指定初始值;
2、使用静态初始化块为类变量指定初始值。
初始化(类加载)的时机
1)创建类实例的时候,分别有:
1、使用new关键字创建实例;
2、通过反射创建实例;
3、通过反序列化方式创建实例。
2)调用某个类的类方法(静态方法)
3)访问某个类或接口的类变量,或为该类变量赋值。
4)初始化某个类的子类。当初始化子类的时候,该子类的所有父类都会被初始化。
5)直接使用java.exe命令来运行某个主类。
除了上面几种方式会自动初始化一个类,其他访问类的方式都称不会触发类的初始化,称为被动引用。
1、子类引用父类的静态变量,不会导致子类初始化。
2、通过数组定义引用类,不会触发此类的初始化
3、引用常量时,不会触发该类的初始化
因为用final修饰某个类变量时,它的值在编译时就已经确定好放入常量池了,所以在访问该类变量时,等于直接从常量池中获取,并没有初始化该类。
初始化的步骤
总结
1、如果该类还没有加载和连接,则程序先加载该类并连接。
2、如果该类的直接父类没有加载,则先初始化其直接父类。
3、如果类中有初始化语句,则系统依次执行这些初始化语句。
在第二个步骤中,如果直接父类又有直接父类,则系统会再次重复这三个步骤来初始化这个父类,依次类推,JVM最先初始化的总是java.lang.Object类。当程序主动使用任何一个类时,系统会保证该类以及所有的父类都会被初始化。