JVM那些事--类的初始化

类的初始化

一个正常的类初始化过程

如果父类还没有完成初始化,则先完成父类的初始化;

  1. Class对象处于被链接过,还未初始化的状态;
  2. 获取锁LC->记录Class对象的状态为初始化过程中->释放锁LC
  3. Class对象的状态为初始化过程中
  4. class文件中的ConstantValue属性中记录的常数值依次赋值给每个finalstatic字段;
  5. 执行类C方法;
  6. 如果类C方法正常完成,则获取锁LC->记录Class对象的状态为已完成初始化->通知所有等待线程->释放锁LC
  7. Class对象的状态为已完成初始化
  8. 如果类C方法执行报错,则则获取锁LC->记录Class对象的状态为初始化报错->通知所有等待线程->释放锁LC
  9. Class对象的状态为初始化报错

如何在并发多线程环境里保证上述初始化过程的线程安全?

假设有两个线程A和线程B,线程A和线程B都执行到步骤2,开始竞争锁LC

方法一:

假设线程A在竞争中获得了锁LC,则记录Class对象的状态为被线程A控制的初始化过程中,然后释放了锁。然后,不管在后面的哪一步被抢占,都执行如下操作:如果线程B获得了锁LC,发现Class对象的状态为被线程A控制的初始化过程中,则线程B就释放锁LC,开始等待一直到收到线程A完成Class对象初始化的通知,正常完成。

哪些情形会触发类的初始化?

  • 虚拟机启动时触发initial类的初始化
  • 子类的初始化触发父类的初始化
  • 调用类库中的反射方法
  • 首次调用java.lang.invoke.MethodHandle实例
  • 虚拟机执行newgetstaticputstaticinvokestatic中任意一个指令

你可能感兴趣的:(JVM那些事--类的初始化)