从 sbt 程序集运行 uber jar 会导致错误:无法找到或加载主类

2022-09-02 23:26:56

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

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核心类,但我没有看到任何打包的类被加载。

这里可能出了什么问题?


答案 1

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

按照 JAR 文件规范,如果存在,则指示要加载 Jar 文件中的哪些包。INDEX.LIST

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

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

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


更新:

经过一些额外的搜索,事实证明默认的合并策略会妥善处理。当自定义合并策略包含处理INDEX.LISTMETA-INF pathSpec


答案 2

推荐