2012-09-26 70 views
4

我不清楚以下內容:
JVM在需要時加載類,例如延遲初始化,對吧?
現在,如果類A確實B類的import哪一類B實際上不是在文件系統(例如B.class被刪除的或者未送達或任何原因)
便無類A得到加載和運行如果沒有方法類B被稱爲?
A無法運行,因爲導入無法解決?
A被加載並運行到某個點?如果導入語句無法解析,會發生什麼情況?

回答

7

import語句只對編譯器很重要。在字節碼中,其他類的所有引用都是完全限定的。這就是爲什麼超級進口在運行時無關緊要的原因。

你的情況,JVM將嘗試加載所需要的加載和驗證A所有類,所以它會嘗試加載B立即,但依賴類懶洋洋地加載只在需要的時候。看看下面的例子:

public class A { 

    public static void bar() { 
     new B().foo(); 
    } 

    public static void main(String[] args) { 
     //bar(); 
    } 

} 

編譯A.java和刪除B.class。沒有調用bar()方法,你的程序將運行得很好。但是,你取消註釋代碼段實際使用B類,一旦你會得到討厭:

Exception in thread "main" java.lang.NoClassDefFoundError: B 
    at A.bar(A.java:4) 
    at A.main(A.java:8) 
Caused by: java.lang.ClassNotFoundException: B 
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366) 
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:423) 
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:356) 
    ... 2 more 

如果B不可用,你會得到NoClassDefFound或相似。

+0

所以這會發生試圖解決'進口'?對。正在構建「A」類? – Jim

+1

@Jim:不,JVM不**解析任何導入,導入在編譯期間被讀取和丟棄。它們不存在於字節碼中。在'.class'文件中,所有的類都是完全合格的。 –

+1

+1我喜歡它什麼時候詳盡,詳細地解釋爲什麼「問題X」不會成爲問題,他們會回來;所以它是一個真正的問題。大聲笑。 –

0

如果A.class需要缺少B.class。 A.class不能被加載。

加載類是recursion operation

當A.class需要B.class時,JVM在PermGen中搜索B.class。如果B.class被加載並存儲在PermGen中,則JVM將not reload B.class直接從PermGen得到,否則JVM將遞歸加載B.class。

當JVM找不到B.class時,它拋出NoClassDefFoundError

See more about NoClassDefFoundError in [Java Specification] :page 319

+0

是的好,但問題是*當這個異常拋出*時出現 – Jim

+0

@Jim [見此](http://docs.oracle.com/javase/specs/jls/se7/jls7.pdf)第319頁。 – lichengwu

相關問題