jvm类加载时机及初始化

3 篇文章 0 订阅

参考书籍:《深入理解Java虚拟机》周志明
1,类的生命周期
类的生命周期2,类的初始化
《Java虚拟机规范》严格规定有且仅有六种情况必须对类立即进行初始化,分别是:
1. 遇到new,getstatic,putstatic,invokestatic这四个字节码指令时,如果类型没有进行初始化,则需要进行初始化。生成四条指令的代码场景:

 1. 使用new关键字实例化对象时 
 2. 读取或设置一个类型的静态字段时(被final修饰,已在编译期把结果放入常量池的静态字段除外)
 3. 调用一个类型的静态方法时
  1. 使用java.lang.reflect包的方法对类型进行反射调用的时候,若没有初始化,则需要先进行初始化
  2. 初始化类的时候,如果发现其父类没有进行初始化,则先触发父类进行初始化
  3. 当虚拟机启动时,用户需要指定一个要执行的主类(包含main方法的类),会先初始化主类
  4. 当使用jdk7新加入的动态语言支持时,如果一个java.lang.invoke.MethodHandle实例最后的解析结果为REF_getStatic,REF_putStatic,REF_invokeStatic,REF_newInvokeSpecial四种类型的方法句柄,若方法句柄没有初始化,则需要先初始化
  5. 当一个接口中定义了jdk8新加入的默认方法时,若有该接口的实现类进行了初始化,那么该接口要在其之前进行初始化

这六种情况被称为主动引用,除此之外,所有引用类型的方式都不会触发初始化,也称为被动引用。被动引用方式:

  1. 通过子类引用父类的静态变量,不会导致子类初始化
public class NotInitTest {
       public static void main(String[] args) {
              // TODO Auto-generated method stub
              System.out.println(Child.value);
       }
}
class Parent{
       static {
              System.out.println("初始化Parent类");
       }
       public static int value = 11;
       
}
class Child extends Parent{
       static {
              System.out.println("初始化Child");
       }
}

// 输出结果
初始化Parent类
11
对于静态字段,只有直接定义这个字段的类才会被初始化,因此通过子类引用父类定义的静态字段,只有父类会被初始化

  1. 通过数组定义来引用类,不会触发此类的初始化
public class NotInitTest {
       public static void main(String[] args) {
              // TODO Auto-generated method stub
              Father [] fathers = new Father[10];
       }
}
class Father{
       static {
              System.out.println("初始化Father类");
       }
       public static int value = 11;
       
}

//输出结果 无
说明没有触发类Father的初始化

  1. 常量在编译阶段会存入调用类的常量池中,本质上没有直接引用到定义常量的类,因此不会触发定义常量的类的初始化
public class NotInitTest {
       public static void main(String[] args) {
              // TODO Auto-generated method stub
              System.out.println(Const.PI);
       }
}
class Const {
       static {
              System.out.println("初始化Const");
       }
       
       public static final double PI = 3.14;
}

// 输出结果
3.14

没有输出“初始化Const”,因此没有对类Const进行初始化

另补充一个知识点:在继承中代码的执行顺序为:

  1. 父类静态对象,父类静态代码块
  2. 子类静态对象,子类静态代码块
  3. 父类非静态对象,父类非静态代码块
  4. 父类构造函数
  5. 子类非静态对象,子类非静态代码块
  6. 子类构造函数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值