2013-04-15 11 views
3

我很困擾ClassLoader嘗試解析僅在特定條件下工作的資源的情況。ClassLoader僅在特定線程中發現資源

用例如下:我將IBM Rational Functional Tester與JBehave結合使用進行自動驗收測試。 JBehave將測試指定爲純文本故事文件。這些故事文件可以引用其他故事文件,即所謂的「給定故事」。 JBehave使用ExecutorService來執行潛在的多線程故事。儘管JBehave在加載文本文件(使用ClassLoader.getResourceAsStream)時沒有問題,但它無法在從ExecutorService啓動的線程中查找相同的文件。

ClassLoader的作用是ContextFinder。在調試應用程序並暫停兩個線程時,最初啓動JBehave的「主線程」和從執行程序服務啓動的「故事線程」運行故事文件,我可以確定類加載程序的實例是相同的。父母也實例等

但在主線程

Thread.currentThread().getContextClassLoader().getResource("HelloWorld.story") 

作品完美地

一個電話,失敗的故事線,並返回null。

從ContextFinder的源代碼判斷,它似乎沒有收集到堆棧中所有類的ClassLoader。所以我試過這個:

SomeClass.class.getClass().getClassLoader().getResource("HelloWorld.story") 

...有相同的結果。

這對我來說太奇怪了。任何用於調試或放棄此行爲顯示的指針都是值得讚賞的!

回答

2

線程上下文類加載器(TCCL)在OSGi中基本上是未定義的。你應該避免使用它。

作爲標準OSGi的擴展,Equinox確實提供了稱爲ContextFinder的東西,它執行堆棧檢查以嘗試在調用堆棧中查找最頂層的OSGi包類加載器。然而,你幾乎沒有任何控制,結果可能會像你所看到的那樣非常出人意料。當然,因爲這是一個Equinox特定的擴展,任何依賴ContextFinder正常工作的代碼都會在所有其他OSGi框架上失敗。

因此,不要浪費時間去嘗試調試,最好不要使用TCCL。如果你想一個資源相對加載到一個特定的類,然後實現它從字面類對象,例如:

MyClass.class.getResource("HelloWorld.story"); 

UPDATESomeClass.class.getClass()

我在你原來的問題注意到了這一點。這個結果將是java.lang.Class本身的類對象。調用getClassLoader()就可以了總是返回JVM引導類加載器....可能不是你想要的!

+0

謝謝,這指出我正確的方向!在JBehave中,我能夠以不同的方式配置測試的執行。而不是使用[LoadFromClasspath]的默認構造函數(http://grepcode.com/file/repo1.maven.org/maven2/org.jbehave/jbehave-core/3.7.5/org/jbehave/core/io/LoadFromClasspath 。java#LoadFromClasspath),它使用TCCL,我現在用「我的」類實例化了LoadFromClasspath,現在類加載器能夠找到所有的資源。 – AndreasEK