2012-06-12 70 views

回答

2

的javadoc說以下有關class loaders

ClassLoader類使用委託模型來搜索類 和資源。 ClassLoader的每個實例都有一個關聯的父類 類加載器。當請求查找類或資源時, ClassLoader實例將在嘗試查找 類或資源本身之前,將對該類或 資源的搜索委託給其父類加載器。虛擬機的內置類加載器 稱爲「引導程序類加載器」,本身不具有父代,但 可能充當ClassLoader實例的父代。

因此,您的問題中的陳述顯然是錯誤的。

在某些情況下,您可能希望創建一個獨立的類加載器,也就是不與應用程序類加載器鏈綁定的類加載器。在這些情況下,你可以創建一個父類爲null的類加載器。 (即在URLClassLoader class中檢查構造函數)

這意味着如果這個獨立的類加載器無法找到/加載給定的類,它將立即失敗並返回ClassNotFoundException。這也意味着你可以有兩個獨立的類加載器層次結構不會相互干擾。

CNC中

我要說明我的答案。假設:

  • 我有一個名爲Creature位於JAR文件的接口稱爲parent.jar
  • 我有一個名爲Jedi的類,位於名爲child.jar的JAR文件中。
  • Jedi實現接口Creature

現在,讓我們創建一個類加載器鏈,與當前系統鏈無關。

ClassLoader parent = new URLClassLoader(new URL[]{parentJar.toURL()}, null); 
ClassLoader child = new URLClassLoader(new URL[]{childJar.toURL()}, parent); 

現在,我們可以要求子類加載器加載類Jedi

Class<?> klass1 = child.loadClass("com.star.wars.Jedi"); 

現在,如果你查詢它的類加載器,你會發現它是由子類加載器加載的。到現在爲止還挺好。但是它實現的接口呢?它取決於它,但Creature接口只對其父類加載器可用,對吧?

那麼,如果你要求klass1.getInterfaces()[0].getClassLoader()你會注意到它是父類加載器。

這證明聲明:

如果A類是由類加載器加載,那麼所有的類A依賴於 會的ClassLoader A.

是完全錯誤的加載。

+0

是的,其實我試圖實現孤立的類加載器。我的疑惑是,在我提供的鏈接中,mainClass已經被URLClassLoader加載,那麼它所依賴的所有類將被同一個加載器(或加載器的父加載器)加載,爲什麼我們需要調用''Thread.currentThread()setContextClassLoader(類加載器);''? –

+0

那麼,如果你的類加載器是鏈中唯一的類加載器,那麼你可以確定它將加載所有的類,但是如果你的鏈中有更多的類加載器(即綁定到不同的URL),那麼一個父母最終可能會加載其孩子或大孩子或偉大的孩子要求的課程,對吧? –

+0

@ James.Xu我已經更新了我的答案,通過提供示例爲您提供更詳細的信息。 –

0

你讀的是正確的。默認情況下,所有類只是相互引用並以相同的ClassLoader結束。你提供的鏈接解釋瞭如何做相反的事情。在同一個JVM中加載的多個類可以具有相同的名稱(包括包名稱),但具有不同的定義。一般來說,當它們來自同一個庫的不同版本時,會發生這種情況。如何確保使用庫版本1的代碼始終可以看到版本1,並且使用庫版本2的代碼始終可以看到版本2?您可以通過您提供的鏈接中所描述的引導類加載器來執行ClassLoader隔離。

+0

感謝您的快速響應。在我提供的鏈接中,''mainClass''已經被URLClassLoader加載,那麼它所依賴的所有類將被同一個加載器(或加載器的父加載器)加載,爲什麼我們需要調用''Thread。 currentThread()setContextClassLoader(類加載器);''? –

+0

該方法讓你告訴代碼你將要調用它應該使用某個類加載器。想象一下,你寫一個運行webapps的服務器。該webapps將有很長的classpaths,但服務器會有短路徑。服務器將由一個類加載器加載,但它必須使用具有較長類路徑的類加載器加載該webapp代碼。說實話,我仍然不明白爲什麼這是必要的。這個鏈接試圖解釋它http://impalablog.blogspot.com/2008/10/using-threads-context-class-loader-in.html。 –