从sbt程序集运行超级jar会导致错误:无法找到或加载主类 [英] Running an uber jar from sbt assembly results in error: Could not find or load main class
问题描述
我使用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屋!