【问题标题】:Running an uber jar from sbt assembly results in error: Could not find or load main class从 sbt 程序集运行 uber jar 会导致错误:无法找到或加载主类
【发布时间】:2018-02-27 11:48:52
【问题描述】:

我有一个使用 sbt 程序集插件打包为 uber-jar 的 spark 作业。 build.sbt 指定一个可运行的 main 作为生成的 uber-jar 的目标

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

正确创建程序集后,运行预期的命令:

java -jar assembly.jar

结果

错误:无法找到或加载主类 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 核心类,但我没有看到任何正在加载的打包类。

这里可能有什么问题?

【问题讨论】:

    标签: java jar classloader sbt-assembly


    【解决方案1】:

    经过广泛调查(阅读:拔毛),事实证明,这种行为是流氓 INDEX.LIST 来自一个扁平 jar 文件的结果,该文件降落在生成的 uber-jar 的 META-INF 目录中.

    JAR file spec 之后,INDEX.LIST(如果存在)指示要加载 Jar 文件中的哪些包。

    为避免这种情况,我们更新了mergeStrategy 规则以避免对生成的META-INF 目录造成任何污染:

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

    这解决了问题并恢复了我的理智。


    更新:

    经过一些额外的搜索,事实证明default merge strategy 妥善处理了INDEX.LIST。当自定义合并策略包含处理 META-INF pathSpec 的案例时,此答案适用

    【讨论】:

    • 这也解决了另一个相关问题,我可以使用 fatjar 将依赖项引入 spark-shell。我可以运行导入语句。但是当我尝试实际使用它们时,我得到一个 java.lang.NoClassDefFoundError 。令人抓狂!
    • 你救了我的命。我简直要疯了。我不想想象你自己经历了什么发现它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-11-17
    • 1970-01-01
    • 1970-01-01
    • 2017-07-30
    • 2016-01-06
    • 1970-01-01
    • 2016-01-18
    相关资源
    最近更新 更多