[英]Generated JAR throws ClassNotFoundException for main class
我正在使用IntelliJ IDEA创建一个JAR。 我为库JAR选择了“来自具有依赖项的模块中的JAR”和“提取到目标JAR”-生成的JAR看起来很好:
myJar.jar
|
+- META-INF
| +- MANIFEST.MF
+- com
| +- my
| +- package
| +- Main.class
+- some dependencies...
我检查了两次:所有必需的依赖项都存在。 MANIFEST.MF
的Main-Class
字段指向正确的主类(在此示例中为com.my.package.Main
)。 我已经在存档工具中打开了文件,并使用对其进行了检查
jar tf myJar.jar
两者都表明所需的类可用(还有Main.class
)。 我不需要IntelliJ向导中的Classpath
字段,因为我不需要任何外部库。 但是,当我发出
java -jar myJar.jar
它引发以下异常:
Error: could not find or load main class com.my.package.Main
Caused by: java.lang.ClassNotFoundException: com.my.package.Main
我通过JetBrains遵循了本指南 ,并且IntelliJ自动将Maven pom.xml
所有依赖关系添加到JAR中,这是正确的。
我是否缺少我应在此处配置的内容,这怎么不起作用?
(注意:当我为库JAR选择“复制到输出文件夹并通过清单链接”时,从该项目生成JAR也不起作用。)
(注2:不幸的是,使用maven-assembly-plugin
并不是一种选择,因为我引用了其他IntelliJ工作区模块,这些模块随后将不包含在内。)
更新:应该按原样工作还显示以下现象:当我解压缩JAR并执行
java -cp . com.my.package.Main
在创建的目录中,它可以正常工作,考虑到Java拒绝加载它,这很奇怪。
就我而言,由于某些签名的JAR依赖项,我的JAR无法正常工作。
这些JAR带有签名和密钥文件,当您嵌入签名的JAR时也会提取它们。 删除它们基本上没有风险,但是它们是您的JAR可能无法正常工作的众多原因之一。
如何从JAR中删除此类签名?
我正在描述Linux / Darwin的以下步骤,但是我认为Windows也有类似的方法。
解压缩您的JAR。
由于JAR只不过是简单的ZIP存档,因此您可以使用unzip
:
mkdir temporaryDirectory unzip myJar.jar -d temporaryDirectory/
-d
选项是可选的,但是因为它设置了目标目录,所以有助于保持目录结构的整洁。
找到签名文件。
签名文件(或密钥)位于META-INF/
目录中,因此请在此处进行更改:
cd temporaryDirectory/META-INF/
接下来,我们需要找到麻烦的文件。 它们具有文件扩展名.SF
(用于签名)和.DSA
作为密钥文件:
ll | grep '.DSA\\|.SF'
删除(或重命名)签名和密钥文件。
重命名这些文件几乎没有好处,您可以稍后再恢复它们(无论出于何种原因),删除它们也可以解决这个问题,但风险更高:
删除中:
rm signature.DSA signature.SF # Either enter the name of the files # instead of 'signature' or use * to delete any: # rm *.DSA *.SF
重命名:
rename 's/\\.DSA$/.DSA.old/' * # Append ".old" to all .DSA files rename 's/\\.SF$/.SF.old/' * # Append ".old" to all .SF files
重新包装您的JAR。
仍在temporaryDirectory/
,我们可以重新打包我们的JAR使其工作:
cd ../ # If you're still in temporaryDirectory/META-INF jar cfm ../myWorkingJar.jar ./META-INF/MANIFEST.MF -C ./ .
说明:
jar cfm
jar
是Java的内置JAR构建器。 用c
调用它意味着我们要创建一个JAR, f
代表输出文件(我们在下面指定), m
代表我们要使用的MANIFEST.MF
。 如果省略m
, jar
会将一个空的MANIFEST.MF
写入JAR。 ../myWorkingJar.jar
f
。 ./META-INF/MANIFEST.MF
cfm
的m
。 -C ./
.class
文件位于此目录( .
)中。 .
(最后一个论点) 如果要详细了解jar
功能,可以使用cvfm
而不是cfm
从上面发出命令( v
表示详细)。
验证它是否有效。
全部设置好了,现在您可以通过发出以下命令来检查您的JAR是否正常运行
java -jar myWorkingJar.jar
删除临时目录。
由于您已完成对JAR的修复,因此可以安全地删除我们创建的临时目录(和/或“损坏的” JAR)。
我创建了一个简单的bash脚本,其中“自动”这个过程中一点点 :
#!/bin/bash
JARNAME=myJar.jar # enter your JAR's name here
OUT_JARNAME=myJar_out.jar # enter your output JAR's name here
# Creating the directory, unpacking the JAR, entering META-INF/
mkdir temp
unzip $JARNAME -d temp
cd temp/META-INF
# Renaming the troublemakers.
rename 's/\.DSA$/.DSA.old/' *
rename 's/\.SF$/.SF.old/' *
# Reassembling the JAR
cd ../
jar cfm ../$OUT_JARNAME ./META-INF/MANIFEST.MF -C ./ .
cd ../
# Uncomment this line if you wish to delete the temp directory upon finish.
# rm -r temp
我希望这可以帮助人们也遇到这个问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.