2017-09-18 65 views
2

我有一個使用sbt程序集插件打包爲超級jar的spark作業。 該build.sbt指定一個可運行的主要正確地創建所得尤伯杯罐從sbt程序集運行一個超級jar導致錯誤:無法找到或加載主類

mainClass in assembly := Some("com.foo.Bar") 

在組裝之後的目標,運行預期的命令:

java -jar assembly.jar 

導致

Error: Could not find or load main class com.foo.Bar

使用另一種方法,如java -cp assembly.jar com.foo.Bar會給出相同的錯誤消息。

然後,我在新目錄中提取了uber-jar的內容。我可以看到我的com/foo/目錄和Bar.class文件。 從提取的根目錄我想:

java -cp . com.foo.Bar 

,我得到正確的結果。

而且試圖找到錯誤的原因,我想:

java -verbose -jar assembly.jar 

我可以看到正在加載的Java核心類,但我沒有看到我的任何包裝類的加載。

這裏可能有什麼錯?

回答

3

經過廣泛的調查(讀:頭髮拉出來),事實證明,這種行爲是從扁平的jar文件降落在META-INF目錄中所產生的尤伯杯罐的一個流氓INDEX.LIST的結果。

JAR file spec之後,INDEX.LIST(如果存在)決定要加載Jar文件中的哪些包。

爲了避免這種情況,我們與規則更新mergeStrategy避免由此產生META-INF目錄的任何污染:

case PathList("META-INF", xs @ _*) => MergeStrategy.discard 

這個固定的問題,回到我的理智。


更新:

後一些額外的搜索,但事實證明,default merge strategy需要的INDEX.LIST適當的照顧。當自定義合併策略包含處理META-INFpathSpec

相關問題