11

我知道newdupinvokespecialastore<init>字节码模式将在有人从 Java 语言的角度实例化 Java 类时调用实例初始化方法,但我从来不知道是谁调用了这个特殊<clinit>方法,什么时候会发生这种情况?

我的猜测是在方法之前<clinit>调用。任何机构都可以给我一些信息来证明这一点吗?这是否记录在 JVM 规范或 Java 语言规范中? <init>

4

3 回答 3

7

JVM 规范§2.9。特殊方法

一个类或接口最多有一个类或接口初始化方法,并通过调用该方法进行初始化(第 5.5 节)。类或接口的初始化方法具有特殊名称<clinit>,不带参数,并且是无效的(第 4.3.3 节)。

该名称<clinit>由编译器提供。因为名称不是有效的标识符,所以不能直接在用 Java 编程语言编写的程序中使用。Java虚拟机隐式调用类和接口初始化方法;它们永远不会从任何 Java 虚拟机指令中直接调用,而只是作为类初始化过程的一部分间接调用。

有关类初始化过程的更多详细信息,请参见第 5 章。

于 2013-04-10T07:17:14.503 回答
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决定了类是否应该在加载后初始化。

于 2013-04-10T07:46:29.527 回答
1

<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
于 2013-04-10T07:23:28.973 回答