2014-06-26 41 views
0

假設我有classpath中2瓶確保每個JAR首先看到了自己的classpath資源

JAR1:

Class1.class 
resource.xml 

JAR2:

Class2.class 
resource.xml 

的類的Class1和Class2中使用的類路徑資源(每個JAR都提供自己的resource.xml並希望讀取它)。

在我的應用程序中,我使用了兩個jar文件,當加載Class1或Class2時,加載的resource.xml是隨機的(兩者之一)。

Class1是否可能總是加載其自己的resource.xml和Class2?

回答

1

我認爲這是不可能做到你想要的。


讓我們開始瞭解如何類加載器和資源裝載工作

  1. 當你調用Class.getResource()它變成以Class.getClassloader().getResource()調用一些事實。

  2. 每個類只有一個類加載器。

  3. 每個類加載器都只有一個父類加載器。

  4. 構建類加載器的方式確保類加載器形成一個嚴格的樹,在樹的根部有所謂的引導類加載器。

  5. 類加載器可以使用兩種策略之一尋找的東西:

    • 先問父類加載器,然後選中這一類加載器的資源,
    • 檢查這個類加載器的資源,然後再詢問父類加載器。

現在,爭論的緣故,讓我們考慮這個例子:

JAR1: 

Class1.class 
resource.xml 
resource1.xml 

JAR2: 

Class2.class 
resource.xml 
resource2.xml 

所以,讓我們考慮我們如何把這個一起:

  • 如果JAR1和JAR2具有相同的類加載器,那麼該類加載器無法知道應首先搜索哪個JAR。類加載器上的getResource()調用不知道原始類是什麼。

  • 假設JAR1和JAR2有不同的類裝載器:

    • 如果JAR2的類加載器是JAR1的母公司,那麼它可以委託給JAR2,但JAR2的類加載器不能委託給JAR1。如果我們調用Class2.class.getResource("resource1.xml"),那麼Class2的類加載器將無法委派給知道「resource1.xml」的類加載器,並且加載將失敗。

    • 如果您翻轉它並使JAR1的類加載器成爲JAR2的父類,那麼我們會發現Class1.class.getResource("resource2.xml")會失敗。

  • 假設我們創建了2類加載器,這兩個知道JAR1和JAR2,也不委託其他。第一個類加載器可以在JAR1中查找資源,然後在JAR2中查找資源,然後在父代中查找資源,第二個類加載器可以在JAR2,JAR1,父代中查找資源。

    目前爲止確定。但是,類加載呢?這裏我們必須是真的很仔細。我們不能允許類加載器可能加載Class1.class的情況。因爲如果發生這種情況,最終會得到兩個具有相同完全限定名稱和不同類加載器的加載類型。但Java類型系統說,給我們兩個不同的類型......這很容易導致意想不到的ClassCastExceptions。所以我們必須確保兩個相應的類加載器不是都加載相同的類。

    但是這導致了另一個問題。如果要求第一個類加載器找到只有其他類加載器可以加載的類,那麼它就不能委託給它......並且最終結果將是您將得到「類未找到」錯誤或異常。


綜上所述,我想我已經覆蓋了所有的合理的類加載器的結構,卻沒有一個人對我提出的例子工作。

有可能「違反規則」並且設置有效的非樹結構化類加載器委託網絡;例如通過使用後門來告訴兩個關於對方的類加載器。然而,你最終會有一個代表循環......這會導致「無限」遞歸。即使這樣做還有其他潛在風險,例如到也依賴類加載器的工作的Java沙盒安全模型。

不要去那裏。找到另一種方式來做到這一點;例如爲這兩個版本的「resource.xml」使用不同的名稱。

+0

是的,我並不喜歡這個主意,但我被問到這是否可能;還有一件事 - 如果應用程序(jar1和jar2的用戶)擁有自己的類加載器(CL)併爲jar1使用單獨的CL併爲jar2單獨使用?這兩個CL都可以不帶父CL,也可以帶JDK CL作爲父帶。基本上我知道jar1和jar2之間不會有連接 - 它們不會互相使用。他們只是碰巧需要一個同名的文件.... :-( –