2013-04-10 35 views
10

我知道DUPinvokespecialASTORE字節碼格局將調用實例初始化方法<init>當有人實例但從Java語言點的Java類,但我從來沒有弄清楚誰調用特殊的<clinit>方法,這是什麼時候發生的?誰調用類初始化方法<clinit>以及何時?

我的猜測是<clinit>被調用之前<init>方法。任何機構可以給我一些信息來證明嗎?這是在JVM規範還是Java語言規範中記錄的?

回答

7

JVM規範§2.9. Special Methods

類或接口具有至多一個類或接口的初始化方法,並通過調用該方法初始化(§5.5)。類或接口的初始化方法具有特殊名稱<clinit>,不帶參數,並且是void(第4.3.3節)。

名稱<clinit>由編譯器提供。由於名稱不是有效的標識符,因此不能直接在用Java編程語言編寫的程序中使用。 類和接口初始化方法由Java虛擬機隱式調用;它們不會直接從任何Java虛擬機指令中調用,而只是間接作爲類初始化過程的一部分進行調用。

有關類初始化過程的更多詳細信息,請參閱Chapter 5

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 
6

<clinit>是javac的添加和類加載後由JVM稱爲靜態方法。我們可以在帶有字節碼輪廓工具的類字節碼中看到這種方法。需要注意的是<clinit>添加只有一個類需要靜動初始化,e.g

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.forNameboolen intialize參數,它決定了在加載後是否應該初始化類。

+1

「請注意,僅在類需要靜態初始化時才添加」 - 任何源代碼? – siledh 2014-04-10 13:52:17

+0

從實踐(測試)說實話,常識也是一樣的,肯定是JLS中的一個段落 – 2014-04-10 14:12:45