类从被加载到虚拟机内存开始到卸载出内存,整个生命周期包括以下七个阶段:

一、类加载前5部分的功能或作用:
-
加载:根据查找路径找到相应的class文件,然后导入。
-
检查:检查加载的class文件的正确性。
-
准备;给类中的静态变量分配内存空间,赋以默认初始值。
-
解析:虚拟机将常量池中的符号引用替换成直接引用的过程。符号引用就理解为一个标示,而在直接引用直接指向内存中的地址。
-
初始化:对静态变量和静态代码块执行初始化工作。
二、类在什么情况下进行加载?
虚拟机对类的加载时机并没有明确的规定,是由具体的虚拟机实现的,当前明确规定了,在以下5种情况下(有且只有),类必须进行初始化(加载、验证、准备必须在初始化之前)。
这5种方式也被称为主动引用,除此之外的其他引用都不会触发初始化,称为被动引用。不会触发初始化,就不会执行静态代码块的方法。
- 遇到new(使用new关键字创建实例对象的时候)、getstatic(读取一个静态变量,被final修饰,已在编译把结果放入常量池的静态变量除外)、putstatic(设置一个静态变量,被final修饰,已在编译把结果放入常量池的静态变量除外)或invokestatic(调用一个类的静态方法)这四条字节码指令的时候,如果类没有进行初始化,则需要先触发其初始化。
- 使用java.lang.reflect方法对类进行反射调用的时候,如果类没有进行初始化,则需要先触发器初始化
- 初始化一个类时,发现其父类没有进行初始化,则需要先触发父类的初始化。
- 虚拟机启动的时候,用户需要指定一个执行的主类(包含main方法的类),虚拟机会先对初始化这个主类
- 当使用JDK1.7的动态语言支持时,如果一个java.lang.invoke.MethodHandle实例最后的解析结果REF_getStatic、REF_putStatic、REF_invokeStatic的方法的句柄,并且这个方法句柄所对应的类没有进行过初始化,则需要先触发其初始化。(使用场景未知)
三、验证
//Parent.java
public class Parent {
static {
System.out.println("我是父类的静态代码块");
}
public static String spName = "父亲名字";
}
//Child.java
public class Child extends Parent{
static {
System.out.println("我是子类的静态代码块");
}
public static String sCode = "001";
public static final int sfAge = 10;
}
//test.java
public static void main(String[] args)
{
System.out.println("**********不会初始化的情况**********");
//引用类的静态常量不会触发定义常量的类的初始化,因为常量在编译阶段已经被放到常量池中
System.out.println(Child.sfAge);
//通过子类引用父类的静态字段,不会导致子类初始化
System.out.println(Child.spName);
System.out.println("**********会初始化的情况**********");
//读取或者设置一个类的静态字段(被final修饰的除外)时
System.out.println(Child.sCode);
}
结果:
**********不会初始化的情况**********
10
我是父类的静态代码块
父亲名字
**********会初始化的情况**********
我是子类的静态代码块
001
扩展
- 执行类的静态方法时,static代码块也会执行,如果是连续执行静态方法的,static代码块只会执行一次。
- 创建一个类的实例时,static代码块也会执行,如果是连续执行创建实例方法的,static代码块只会执行一次。
//Child.java
public class Child extends Parent{
static {
System.out.println("我是子类的静态代码块");
}
public static void SayHello()
{
System.out.println("大家好,我是Child对象");
}
}
//test.java
Child.SayHello();
Child.SayHello();
Child.SayHello();
Child.SayHello();
//结果
我是父类的静态代码块
我是子类的静态代码块
大家好,我是Child对象
大家好,我是Child对象
大家好,我是Child对象
大家好,我是Child对象
参考