繁体   English   中英

生成的JAR会为主类抛出ClassNotFoundException

[英]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.MFMain-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也有类似的方法。

  1. 解压缩您的JAR。
    由于JAR只不过是简单的ZIP存档,因此您可以使用unzip

     mkdir temporaryDirectory unzip myJar.jar -d temporaryDirectory/ 

    -d选项是可选的,但是因为它设置了目标目录,所以有助于保持目录结构的整洁。

  2. 找到签名文件。
    签名文件(或密钥)位于META-INF/目录中,因此请在此处进行更改:

     cd temporaryDirectory/META-INF/ 

    接下来,我们需要找到麻烦的文件。 它们具有文件扩展名.SF (用于签名)和.DSA作为密钥文件:

     ll | grep '.DSA\\|.SF' 
  3. 删除(或重命名)签名和密钥文件。
    重命名这些文件几乎没有好处,您可以稍后再恢复它们(无论出于何种原因),删除它们也可以解决这个问题,但风险更高:

    • 删除中:

       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 
  4. 重新包装您的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 如果省略mjar会将一个空的MANIFEST.MF写入JAR。
    • ../myWorkingJar.jar
      这是我们要将JAR输出到的路径。 它属于我们先前指定的f
    • ./META-INF/MANIFEST.MF
      这是我们要使用的清单文件。 它属于cfmm
    • -C ./
      这意味着我们的.class文件位于此目录( . )中。
    • . (最后一个论点)
      这指定我们要将此目录添加到JAR。

    如果要详细了解jar功能,可以使用cvfm而不是cfm从上面发出命令( v表示详细)。

  5. 验证它是否有效。
    全部设置好了,现在您可以通过发出以下命令来检查您的JAR是否正常运行

     java -jar myWorkingJar.jar 
  6. 删除临时目录。
    由于您已完成对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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM