我知道new,dup,invokespecial和astore<init>
字节码模式将在有人从 Java 语言的角度实例化 Java 类时调用实例初始化方法,但我从来不知道是谁调用了这个特殊<clinit>
方法,什么时候会发生这种情况?
我的猜测是在方法之前<clinit>
调用。任何机构都可以给我一些信息来证明这一点吗?这是否记录在 JVM 规范或 Java 语言规范中? <init>
<clinit>
是javac添加的静态方法,类加载后被JVM调用。我们可以使用字节码大纲工具在类字节码中看到这个方法。请注意,<clinit>
仅当类需要静态初始化时才添加,例如
public class Test1 {
static int x = 1;
public static void main(String[] args) throws Exception {
}
}
public class Test2 {
static final int x = 1;
public static void main(String[] args) throws Exception {
}
}
Test1 有<clinit>
,因为它的字段x
需要初始化为 1;而 Test2 没有<clinit>
方法,因为它x
是一个常数。
有趣的是,它的Class.forName
参数boolen intialize
决定了类是否应该在加载后初始化。
<clinit>
是类的静态初始化块,静态字段初始化及其由JVM调用。
Java 规范说, http: //java.sun.com/docs/books/jvms/second_edition/html/Overview.doc.html#12174
The initialization method of a class or interface is static and takes no arguments. It has the special name <clinit>. This name is supplied by a compiler. Because the name <clinit> is not a valid identifier, it cannot be used directly in a program written in the Java programming language. Class and interface initialization methods are invoked implicitly by the Java virtual machine