簡體   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