我知道新,DUP,invokespecial和ASTORE字節碼格局將調用實例初始化方法<init>
當有人實例但從Java語言點的Java類,但我從來沒有弄清楚誰調用特殊的<clinit>
方法,這是什麼時候發生的?誰調用類初始化方法<clinit>以及何時?
我的猜測是<clinit>
被調用之前<init>
方法。任何機構可以給我一些信息來證明嗎?這是在JVM規範還是Java語言規範中記錄的?
我知道新,DUP,invokespecial和ASTORE字節碼格局將調用實例初始化方法<init>
當有人實例但從Java語言點的Java類,但我從來沒有弄清楚誰調用特殊的<clinit>
方法,這是什麼時候發生的?誰調用類初始化方法<clinit>以及何時?
我的猜測是<clinit>
被調用之前<init>
方法。任何機構可以給我一些信息來證明嗎?這是在JVM規範還是Java語言規範中記錄的?
JVM規範§2.9. Special Methods:
類或接口具有至多一個類或接口的初始化方法,並通過調用該方法初始化(§5.5)。類或接口的初始化方法具有特殊名稱
<clinit>
,不帶參數,並且是void(第4.3.3節)。名稱
<clinit>
由編譯器提供。由於名稱不是有效的標識符,因此不能直接在用Java編程語言編寫的程序中使用。 類和接口初始化方法由Java虛擬機隱式調用;它們不會直接從任何Java虛擬機指令中調用,而只是間接作爲類初始化過程的一部分進行調用。
有關類初始化過程的更多詳細信息,請參閱Chapter 5。
<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
<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.forName
有boolen intialize
參數,它決定了在加載後是否應該初始化類。
「請注意,僅在類需要靜態初始化時才添加」 - 任何源代碼? –
siledh
2014-04-10 13:52:17
從實踐(測試)說實話,常識也是一樣的,肯定是JLS中的一個段落 – 2014-04-10 14:12:45