从sbt程序集运行超级jar会导致错误:无法找到或加载主类 [英] Running an uber jar from sbt assembly results in error: Could not find or load main class

查看:1052
本文介绍了从sbt程序集运行超级jar会导致错误:无法找到或加载主类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a spark job packaged as an uber-jar using the sbt assembly plugin. The build.sbt specifies a runnable main to be the target of the resulting uber-jar

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

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

After the assembly is correctly created, running the intended command:

java -jar assembly.jar

结果


错误:无法找到或加载主类com.foo.Bar

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

使用替代方法,如 java - cp assembly.jar com.foo.Bar 给出了相同的错误信息。

Using the an alternative method, like java -cp assembly.jar com.foo.Bar gives the same error message.

然后,我在一个uber-jar中提取了内容。新目录。我可以看到我的 com / foo / 目录和 Bar.class 文件。
从我尝试的解压缩目录的根目录开始:

Then, I extracted the contents of the uber-jar in a new directory. I can see my com/foo/ directory and the Bar.class file. From the root of the extracted directory I tried:

java -cp . com.foo.Bar

我得到了正确的结果。

进一步试图找出错误的原因,我试过:

Further trying to find the reason of the error, I tried:

java -verbose -jar assembly.jar

我可以看到正在加载的java核心类,但我没有看到我的任何打包正在加载的类。

I can see the java core classes being loaded, but I don't see any of my packaged classes being loaded.

这里可能出现什么问题?

What can possibly be wrong here?

推荐答案

经过广泛的调查(阅读:拔出头发),事实证明这种行为是由于一个平铺的jar文件登陆的流氓 INDEX.LIST 的结果生成的超级jar的 META-INF 目录。

After an extensive investigation (read: pulling hairs out), it turns out that this behavior is the result of a rogue INDEX.LIST from one of the flattened jar files landing in the META-INF directory of the resulting uber-jar.

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

Following the JAR file spec, the INDEX.LIST, if present, dictates what packages from the Jar file are to be loaded.

为了避免这种情况,我们使用规则更新了 mergeStrategy ,以避免对结果<$ c $造成任何污染c> META-INF 目录:

To avoid this, we updated the mergeStrategy with a rule to avoid any pollution of the resulting META-INF directory:

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

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

This fixed the issue and returned my sanity.

更新:

经过一些额外搜索后,发现默认合并策略正确处理 INDEX.LIST 。当自定义合并策略包含处理 META-INF pathSpec

After some extra searching, it turns out that the default merge strategy takes proper care of INDEX.LIST. This answer applies when the customized merge strategy contains cases that handle the META-INF pathSpec

这篇关于从sbt程序集运行超级jar会导致错误:无法找到或加载主类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆