2008-10-30 54 views
53

我有一個應用程序,我試圖將其包裝到一個jar中以便於部署。當作爲一組可從CLASSPATH訪問的類運行時,應用程序編譯並運行良好(在Windows cmd窗口中)。但是,當我罐子了我的課,並嘗試在同一個cmd窗口的Java 1.6中運行它,我開始越來越異常:NoClassDefFoundError嘗試運行我的jar與java.exe -jar ...有什麼不對?

C:\dev\myapp\src\common\datagen>C:/apps/jdk1.6.0_07/bin/java.exe -classpath C:\myapp\libs\commons -logging-1.1.jar -server -jar DataGen.jar 
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory 
    at com.example.myapp.fomc.common.datagen.DataGenerationTest.<clinit>(Unknown Source) 
Caused by: java.lang.ClassNotFoundException: org.apache.commons.logging.LogFactory 
    at java.net.URLClassLoader$1.run(URLClassLoader.java:200) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.net.URLClassLoader.findClass(URLClassLoader.java:188) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306) 
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:276) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:251) 
    at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319) 
    ... 1 more 

有趣的是,有問題的LogFactory似乎是在共享記錄-1.1 .jar,它位於指定的類路徑中。該jar文件(是的,它真的存在):

C:\dev\myapp\src\common\datagen>dir C:\myapp\libs\commons-logging-1.1.jar 
Volume in drive C is Local Disk 
Volume Serial Number is ECCD-A6A7 

Directory of C:\myapp\libs 

12/11/2007 11:46 AM   52,915 commons-logging-1.1.jar 
      1 File(s)   52,915 bytes 
      0 Dir(s) 10,956,947,456 bytes free 

的共享記錄-1.1.jar文件的內容:

C:\dev\myapp\src\common\datagen>jar -tf C:\myapp\libs\commons-logging-1.1.jar 
META-INF/ 
META-INF/MANIFEST.MF 
org/ 
org/apache/ 
org/apache/commons/ 
org/apache/commons/logging/ 
org/apache/commons/logging/impl/ 
META-INF/LICENSE.txt 
META-INF/NOTICE.txt 
org/apache/commons/logging/Log.class 
org/apache/commons/logging/LogConfigurationException.class 
org/apache/commons/logging/LogFactory$1.class 
org/apache/commons/logging/LogFactory$2.class 
org/apache/commons/logging/LogFactory$3.class 
org/apache/commons/logging/LogFactory$4.class 
org/apache/commons/logging/LogFactory$5.class 
org/apache/commons/logging/LogFactory.class 
... (more classes in commons-logging-1.1 ...) 

是的,共享記錄具有的LogFactory類。最後,我罐子的清單的內容:

Manifest-Version: 1.0 
Ant-Version: Apache Ant 1.6.5 
Created-By: 10.0-b23 (Sun Microsystems Inc.) 
Main-Class: com.example.myapp.fomc.common.datagen.DataGenerationTest 
Class-Path: commons-logging-1.1.jar commons-lang.jar antlr.jar toplink 
.jar GroboTestingJUnit-1.2.1-core.jar junit.jar 

這難倒我,和任何同事現在我已經竊聽了超過一天。只是爲了剔除答案,至少現在第三方解決方案可能是由於許可限制和公司政策(例如:用於創建exe或打包jar的工具)。最終目標是創建一個jar文件,可以從我的開發Windows機器複製到Linux服務器(使用任何依賴jar)並用於填充數據庫(因此,classpaths可能在開發和部署環境之間有所不同)。任何神祕的線索將不勝感激!

回答

54

-jar選項與-classpath互斥。見老描述here

罐子

執行封裝在JAR文件的程序。第一個參數是JAR文件的名稱,而不是啓動類名稱。爲了使這個選項起作用,JAR文件的清單必須包含一個Main-Class:classname形式的行。這裏,classname標識具有公共靜態void main(String [] args)方法的類,該方法用作應用程序的起點。

有關使用Jar文件和Jar文件清單的信息,請參閱Jar工具參考頁和Java Tutorial的Jar蹤跡。

當您使用此選項時,JAR文件是所有用戶類的來源,並且其他用戶類路徑設置將被忽略。

一個快速和骯髒的黑客是到類路徑追加到引導類路徑:

-Xbootclasspath/A:路徑

指定的冒號分隔路徑directires,JAR歸檔文件和ZIP歸檔文件,以追加到默認引導程序類路徑。

但是,正如@Dan所說的,正確的解決方案是確保您的JAR Manifest包含所需JAR的類路徑。

+1

最好是在JAR的清單中指定一個類路徑。 bootclasspath用於替換系統類。 – 2008-10-30 13:53:13

+0

正確 - 將編輯它清楚這只是一個解決方法。 – toolkit 2008-10-30 14:01:15

+0

啊哈!而已!我知道我一定有一些簡單的東西,我錯過了。只是沒有人在這裏與罐子工作足以注意到我的錯誤! – 2008-10-30 14:55:50

4

,如果你在程序中使用外部庫,你嘗試,因爲類路徑的問題等

在一個jar文件就不是那麼簡單打包在一起的一切,我寧願使用OneJar這個問題。

27

可以省略-jar選項,並啓動jar文件是這樣的:

java -cp MyJar.jar;C:\externalJars\* mainpackage.MyMainClass

0

我發現,當我使用的是顯明罐子類路徑的上市需要有一個空間後,每個罐子的列表例如「required_lib/sun/pop3.jar required_lib/sun/smtp.jar」。即使它是列表中的最後一個。

15

這是正在發生的問題,

如果JAR文件是從已加載「C:\ java的\ APPS \ appli.jar」,和你的清單文件具有類路徑:參考「LIB/other.jar「,類加載器將在」other.jar「中查找」C:\ java \ apps \ lib \「。它不會查看JAR文件條目「lib/other.jar」。

解決方案: -

  1. 右鍵單擊項目,選擇導出。
  2. 選擇Java文件夾並在其中選擇Runnable JAR文件而不是JAR文件。
  3. 選擇適當的選項並在庫處理部分選擇第三個選項,即(將所需的庫複製到生成的JAR旁邊的子文件夾中)。

[EDIT =第三選項生成除罐子的文件夾,第二選項(「包所需的庫到生成的JAR」)也可以有您的罐子中。 ]

  1. 單擊完成,您的JAR將與包含清單文件中提到的JARS的文件夾一起在指定的位置創建。
  2. 打開終端,提供正確的路徑,你的罐子,使用此命令Java的罐子abc.jar運行

    現在會發生什麼是類加載器會在正確的文件夾以來的引用JARS現在它們出現在包含您的應用程序JAR的相同文件夾中。現在沒有引發「java.lang.NoClassDefFoundError」異常。

這對我有效......希望它也適用於您!

2

我有同樣的問題,我的罐子 解決

  1. 創建MANIFEST.MF文件:

清單-版本:1。0

密封:真

類路徑: LIB/jarX1.jar LIB/jarX2.jar LIB/jarX3.jar

主類:com.MainClass

  • 右擊項目,選擇導出。
  • 選擇出口用於檢查項目中的所有文件夾outpout

  • 選擇使用現有的工作區從清單並選擇MANIFEST.MF文件
  • 這對我有用:)

    相關問題