我正在使用IntelliJ IDEA创建一个JAR。我为库JAR选择了“来自具有依赖项的模块中的JAR”和“提取到目标JAR”-生成的JAR看起来还不错:
myJar.jar
|
+- META-INF
| +- MANIFEST.MF
+- com
| +- my
| +- package
| +- Main.class
+- some dependencies...
我检查了两次:所有必需的依赖项都存在。 Main-Class
中的MANIFEST.MF
字段指向正确的主类(在本示例中为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
我遵循了this guide by JetBrains
,并且IntelliJ自动添加了来自Maven pom.xml
的所有依赖关系以将其提取到JAR中,这是正确的。
我是否缺少在此处配置的内容?为什么不起作用?
(注意:当我为库JAR选择“复制到输出文件夹并通过清单链接”时,从该项目生成JAR也不起作用。)
(注2:遗憾的是,不能使用maven-assembly-plugin
,因为我引用了其他IntelliJ工作区模块,这些模块随后将不包含在内。)
更新:按原样工作还显示以下现象:当我解压缩JAR并执行
java -cp . com.my.package.Main
在创建的目录中,它可以正常工作,考虑到Java拒绝加载它,这很奇怪...
答案 0 :(得分:0)
在我的情况下,由于某些签名的JAR依赖项,我的JAR无法正常工作。
这些JAR带有签名和密钥文件,当您嵌入签名的JAR时也会提取它们。基本上没有删除它们的风险,但这是您的JAR可能无法正常工作的众多原因之一。
如何从JAR中删除此类签名?
我正在描述Linux / Darwin的以下步骤,但我认为Windows也有类似的方法。
解压缩您的JAR。
由于JAR只不过是简单的ZIP存档,因此您可以使用2018-07-02 20:25:08.208812 <br>
2018-07-02 21:25:08.208812<br>
2018-07-02 22:25:08.208812<br>
2018-07-02 23:25:08.208812<br>
2018-07-02 24:25:08.208812<br>
2018-07-02 01:25:08.208812<br>
2018-07-02 02:25:08.208812<br>
2018-07-02 03:25:08.208812<br>
2018-07-02 04:25:08.208812<br>
2018-07-02 05:25:08.208812<br>
2018-07-02 06:25:08.208812<br>
2018-07-02 07:25:08.208812<br>
2018-07-02 08:25:08.208812<br>
2018-07-02 09:25:08.208812<br>
2018-07-02 10:25:08.208812<br>
2018-07-02 11:25:08.208812<br>
2018-07-02 12:25:08.208812<br>
2018-07-02 13:25:08.208812<br>
2018-07-02 14:25:08.208812<br>
2018-07-02 15:25:08.208812<br>
2018-07-02 16:25:08.208812<br>
2018-07-02 17:25:08.208812<br>
2018-07-02 18:25:08.208812<br>
2018-07-02 19:25:08.208812<br>
2018-07-02 20:25:08.208812<br>
:
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
重新打包JAR。
仍在rename 's/\.DSA$/.DSA.old/' * # Append ".old" to all .DSA files
rename 's/\.SF$/.SF.old/' * # Append ".old" to all .SF files
中,我们可以重新打包JAR使其工作:
temporaryDirectory/
说明:
cd ../ # If you're still in temporaryDirectory/META-INF
jar cfm ../myWorkingJar.jar ./META-INF/MANIFEST.MF -C ./ .
jar cfm
是Java的内置JAR构建器。用jar
调用它意味着我们要创建一个JAR,c
代表输出文件(我们在下面指定),而f
代表我们想要的m
采用。如果省略MANIFEST.MF
,则m
会将一个空白的jar
写入JAR。MANIFEST.MF
../myWorkingJar.jar
。f
./META-INF/MANIFEST.MF
的{{1}}。m
cfm
文件位于此目录(-C ./
)中。.class
(最后一个参数)如果要详细描述.
的工作,可以使用.
而不是jar
(cvfm
表示详细信息)从上方发出命令。
验证它是否有效。
全部设置好了,现在您可以通过发出
cfm
删除临时目录。
由于您已经完成了JAR的修复,因此可以安全地删除我们创建的临时目录(和/或“损坏的” JAR)。
我已经创建了一个简单的BASH脚本,该脚本可以“自动”完成该过程,只需一点点:
v
我希望这可以帮助人们也遇到这个问题。