JVM如何决定初始化类的顺序(调用<clinit>)?</clinit>

时间:2013-04-04 04:04:48

标签: jvm

据我所知,当JVM加载并为A的clinit生成代码时,如果遇到未解析的B类,编译器将首先发出一个方法调用JVM内部初始化B,然后编译方法调用/字段使用B通常。因此,在运行时,确保在使用其字段或方法之前初始化B.

如果我在上面犯了任何错误,请纠正我。

然后我不明白JVM如何处理下面的情况。

public class A {
  public static A a = new A(B.b);
  public A(B b) {
    a = null;
  }

  public static void main(String[] args) {
    System.out.println(a == null);
  }
}

public class B {
  public static B b = new B(A.a);
  public B(A a) {}
}

有人可以解释这两个类是如何初始化的,因为它们都需要先将其他部分初始化?为什么A中的main方法返回false,因为静态字段a应该在A的构造函数中设置为null?

1 个答案:

答案 0 :(得分:2)

第二个问题很简单; A静态初始化的操作顺序为:B.b被评估,new A(B.b)被评估(将a设置为null),{{1} }被分配a。如果创建了new A(B.b)的任何其他实例,则A将为null。我认为如果没有关于类初始化的详细知识,这应该很容易看到。

第一个问题涉及更多。 JLS的相关章节是chapter 12 on execution。基本思路是:先加载一个类,然后将其链接,然后进行初始化。作为联系的一部分,课程准备;这是在创建静态字段并将其设置为默认值时,对于引用(JLS 12.3.2a - 这是在null初始化之前发生的。

所以事情按此顺序发生:static已加载并关联,因此A初始化为a。然后运行静态初始化程序,因此需要评估null。现在new A(B.b)已加载并链接,并且其静态初始化程序已运行,并且B已经过评估,此时new B(A.a)a并且没有任何特殊情况发生。然后运行null的构造函数,并将新创建的对象分配给A