2012-08-14 116 views
0

我正在使用工作程序JVM執行各種操作的應用程序服務器上工作。Jar文件自發地無法找到內部根資源

使用-cp開關啓動worker jvms,並指定包含供應商庫和其他重要功能的JAR文件。

我有一個非常有趣的問題,其中jar文件CLASSES加載和正確執行代碼,但任何時候他們試圖訪問資源內的jar文件(具體與getResourceAsStream()方法),然後它吹起聲稱它不能找到它。我已經驗證了這些資源肯定存在於正在加載的JAR中,事實上,如果我操縱JAR以在外部定位資源,它就可以工作。問題是這些都是專有的庫,並沒有與源代碼,所以我陷入了癱瘓,我必須通過反編譯和方法入口斷點來做所有事情。

也許最奇怪的部分是這些庫已經改變了很多個月,並且一直在其他(包括生產)應用服務器上工作。

他們是JRE 1.6.0_17

所以我的問題是

  • 爲什麼會用-cp條目的JVM能夠從罐子裏裝載類而不是資源
  • 做任何事情在這個領域從JRE 1.6.0_06變爲1.6.0_17(這已經在最近發生了變化)

爲了闡明,在JAR結構中,這些資源在jar的根上,即:

resource.prop 
META-INF/Manifest 
package/package/class.class 

JAR本身在加載時顯然位於類路徑中。 但是,所有以下決心空的(是的,這是推動我堅果所以我沒有真正嘗試所有3):

Jarclass.getClassLoader().getResourceAsStream("./resource.prop"); 
Jarclass.getClassLoader().getResourceAsStream("/resource.prop"); 
Jarclass.getClassLoader().getResourceAsStream("resource.prop"); 

這類似於Can't access resource in a JAR on all computers但沒有解決這個問題。

+0

,想到的唯一的事情是:JAR的可使用依賴於一些奇怪的行爲在JRE實現自定義的類裝載器(寫一個類加載器是不平凡的)。問題一般侷限於一家供應商的圖書館嗎?如果你使用Jarclass.getClassLoader()。toString(),它是否表明這不是由JRE創建的ClassLoader? – Durandal 2012-08-14 17:24:49

+0

令人難以置信的富有洞察力的評論預測了我在我的原始文章中甚至沒有提到的東西。你是絕對正確的,有一個供應商正在使用自定義類加載器,並且它正在重載JRE標準類加載器,特別是加載資源。我的所有圖書館都沒有改變,但我沒想過要檢查其他包含更改的類加載器的庫。我研究了它,發現這是問題 - 供應商在對自定義類加載器所做的更改中犯了錯誤。謝謝! – 2012-08-15 18:15:46

回答

0

您是否檢查過JAR中的manifest.mf文件?這是控制用於加載JAR內部資源的類路徑的最簡單的方式之一。

從JAR讀取資源只與用於加載JAR的類路徑部分相關。對於類文件,JAR中的文件夾結構足以讓類加載器加載類,基本上是[CLASSPATH]/[Package]/[Classname]。

對於資源來說,這是另一回事。 JAR的根目錄被添加到CLASSPATH而不是任何子目錄,所以如果「resource.prop」在jar的根目錄下,你提供的三個例子中的任何一個都可以工作。既然你說他們已經在罐子的根部,它只會加深這個謎團。

JAR是否發生了變化,就像舊版本一樣工作,而新版本沒有?

最近更改了您的應用服務器的CLASSPATH設置嗎?我們遇到了IBM的WebSphere Application Server問題,我們必須將類加載器的規則設置爲'最後一個父'(至少如果我的內存不會讓我失敗),那麼它將首先使用來自JVM實例的Classpath,然後使用WebSphere的類加載器,因爲我們加載了log4j。比IBM開始在更新版本的WebSphere中包含的那個版本舊的jar。

另一種選擇是擴大JAR,更新MANIFEST.MF文件,以包括對性能絕對引用,然後將文件重新壓縮到一個定製版本。

0

檢查顯示目錄的名稱在非工作罐放置。當我的應用程序被複制到目錄中時,我遇到了類似的問題,其名稱中的符號爲!%