我知道新, dup , invokespecial 和 astore 字节码模式将调用实例初始化方法<init>
当有人从Java语言的角度来看Java类时,但我从来没有弄清楚是谁调用了特殊的<clinit>
方法,这是什么时候发生的?
我的猜测是<clinit>
在 <init>
方法之前被调用。任何机构都可以给我一些信息来证明吗?这是在JVM规范还是Java语言规范中记录的?
答案 0 :(得分:7)
JVM规范§2.9. Special Methods:
类或接口最多只有一个类或接口初始化方法,并通过调用该方法进行初始化(第5.5节)。类或接口的初始化方法具有特殊名称
<clinit>
,不带参数,并且是无效的(§4.3.3)。名称
<clinit>
由编译器提供。因为名称不是有效的标识符,所以它不能直接用在用Java编程语言编写的程序中。 Java虚拟机隐式调用类和接口初始化方法;它们永远不会直接从任何Java虚拟机指令调用,但只能作为类初始化过程的一部分间接调用。
有关类初始化过程的更多详细信息,请参阅Chapter 5。
答案 1 :(得分:6)
<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
param,用于确定是否应在加载后初始化类。
答案 2 :(得分:1)
<clinit>
是类的静态初始化块,静态字段初始化及其由JVM调用。
Java Spec说, 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