疯狂java


您现在的位置: 疯狂软件 >> 新闻资讯 >> 正文

Java虚拟机 类初始化 阶段


 

        Java虚拟机使用某个类的过程,可分为七个阶段:

  加载 - 验证 - 准备 - 解析 - 初始化 - 使用 - 卸载

  本文只介绍在什么情况下对类进行初始化。

  Java虚拟机规范对何时进行类的初始化做了严格规范,有且只有四种情况:

  1. 虚拟机启动时,指定的主类。

  包含main方法的类。

  2. 遇到new、getstatic、putstatic、invokestatic四条指令时。

  new:使用new关键字实例化对象。

  getstatic:读引用一个类的静态字段。

  putstatic:写引用一个类的静态字段。

  invokestatic:调用一个类的静态方法。

  3. 初始化一个类时,先初始化其父类。

  接口则不是,只有真正引用到了父接口时,才会初始化。

  4. 对类进行反射调用时。

  测试代码:

  MainClass:

  [java] view plaincopy

  package com.xuefeng.jvm.load;

  /**

  * 初始化类的时机

  * 1. 虚拟机启动时指定的主类

  * 2. new某类的对象时、引用某类的static变量时、设置某类的变量时、调用某类的static方法时

  * 3. 初始化一个类时,先初始化其父类。接口则不是,真正使用到了父接口时,才会初始化父接口。

  * 4. 通过反射调用某类时

  * @author xuefeng

  *

  */

  public class MainClass {

  static {

  System.out.println("MainClass init.");

  }

  // 1

  public static void main(String[] args) throws ClassNotFoundException {

  // // 2

  // System.out.println("SuperClass.F_V1 : " + SuperClass.F_V1);

  // System.out.println("SuperClass.v1 : " + SuperClass.v1);

  // // 3

  // SubClass s1 = new SubClass();

  // 3.1 如果通过子类名引用父类的static变量,是否会触发子类的初始化?

  // 这取决于具体的虚拟机实现,Sun HotSpot虚拟机此时是不会触发子类的初始化的。

  System.out.println(SubClass.v1);

  // 4

  Class.forName("com.xuefeng.jvm.load.SubClass");

  }

  }

  SuperClass:

  [java] view plaincopy

  package com.xuefeng.jvm.load;

  public class SuperClass {

  static {

  System.out.println("SuperClass init.");

  }

  /**

  * 引用v1时,会初始化SuperClass

  */

  public static int v1 = 1;

  /**

  * 引用F_V1时,不会初始化SuperClass

  * static final的变量,已经在编译器放到了常量池里

  */

  public static final int F_V1 = 1;

  }

  SubClass:

  [html] view plaincopy

  package com.xuefeng.jvm.load;

  /**

  *

  * @author xuefeng

  *

  */

  public class SubClass extends SuperClass {

  static {

  System.out.println("SubClass init.");

  }

  }