Java 类加载过程中的初始化

2018/07/14 类加载

Java类加载过程中的初始化

Java 类加载过程分为load,link(verify,prepare,resolve),initialising,use,unloading等。其中initialising阶段分为类初始化cinit和实例init的初始化。注意类初始化只会一次,实例初始化会多次。

类初始化

初始化时机

类初始化 :就是类第一次加载到内存时进行的过程。类初始化只进行一次(前提是被同一类加载器加载),后续使用 new 等实例化对象时都不在进行初始化了,所以类初始化只运行一次。初始化的都是属于类(而不是实例)的内容(静态),所以对所有实例共享。

触发类初始化的时机是调用类的静态变量和方法。如何理解?

我们知道具体触发点有:

  • new 对象(对象的构造方法类似与静态方法)
  • putStatic 写静态变量
  • getStatic 读静态变量
  • invokeStatic 调用静态方法
  • 反射初始化对象 newInstance
  • main方法中的类
  • 初始化子类时,先初始化父类
  • jdk7 动态语言?

初始化干了啥

  • 在类初始化之前的准备阶段,虚拟机会将类变量(static 修饰的变量)分配内存并设置零值。
  • 在类初始化阶段,执行类构造器 () 方法
    • 收集所有类初始化代码和 static {} 域的代码,收集在一起成为 () 方法
    • 子类初始化时会首先调用父类的 () 方法
    • JVM 会保证 () 方法的线程安全,保证同一时间只有一个线程执行

实例初始化

实例初始化 :也就是实例化对象时每次都会进行的过程,初始化属于实例的内容(非静态),没有实例所拥有的实例内容是不共享的,独有的。

触发时机

new,反射初始化对象都会触发对象实例的初始化。和类的初始化有一部分重合,但是类初始化时实例不一定初始化。比如:

MyClassLoader mcl = new MyClassLoader(); 
// Class<?> clazz = mcl.loadClass("People"); // 类初始化
Class<?> clazz = Class.forName("People", true, mcl); // 类初始化
Object obj = clazz.newInstance(); //实例初始化

干了啥

  • JVM 收集实例初始化变量和 {} 域组合成实例初始化方法
  • 实例初始化时首先执行 () 方法,然后执行构造函数
  • 子类通过构造函数构造实例时会首先调用父类的 () 方法和父类的构造函数,如果没有显示调用父类的构造函数,那么 JVM 会自动调用父类的无参构造函数,保证父类构造函数一定被调用,然后再是子类自己的 () 方法和构造函数;

Search

    Table of Contents