[英]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.