web-dev-qa-db-ja.com

Java.exe -jarでjarを実行しようとしたときにNoClassDefFoundErrorが発生しました。何が問題なのですか?

デプロイを容易にするために、jarにラップしようとしているアプリケーションがあります。 CLASSPATHから到達可能なクラスのセットとして実行すると、アプリケーションはコンパイルされ、(Windowsのcmdウィンドウで)正常に実行されます。しかし、クラスをjarし、同じcmdウィンドウでJava 1.6で実行しようとすると、例外が発生し始めます。

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は、指定されたクラスパスにあるcommons-logging-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

Commons-logging-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 ...)

はい、commons-loggingには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

これは私を困惑させ、私が1日以上も悩んでいた同僚たちを困らせました。答えを抜くために、少なくとも今のところ、これに対するサードパーティのソリューションは、おそらくライセンスの制限と会社のポリシー(例:exeの作成またはjarのパッケージ化)のために出ています。最終的な目標は、開発用のWindowsボックスからLinuxサーバーに(依存するjarを使用して)コピーして、データベースの設定に使用できるjarを作成することです(クラスパスは開発環境とデプロイメント環境で異なる可能性があります)。この謎の手がかりは大歓迎です!

55
Ogre Psalm33

-jarオプションは、-classpathと相互に排他的です。古い説明を参照してください here

-jar

JARファイルにカプセル化されたプログラムを実行します。最初の引数は、スタートアップクラス名ではなく、JARファイルの名前です。このオプションが機能するためには、JARファイルのマニフェストにMain-Class:classnameという形式の行が含まれている必要があります。ここで、classnameは、アプリケーションの開始点として機能するpublic static void main(String [] args)メソッドを持つクラスを識別します。

JarファイルおよびJarファイルマニフェストの操作については、JarツールのリファレンスページとJavaチュートリアルのJarトレイルを参照してください。

このオプションを使用すると、JARファイルはすべてのユーザークラスのソースとなり、他のユーザークラスパス設定は無視されます。

手っ取り早い方法は、クラスパスをbootstrapクラスパスに追加することです:

-Xbootclasspath/a:path

ディレクトリ、JARアーカイブ、Zipアーカイブのコロン区切りのパスを指定して、デフォルトのbootstrapクラスパスに追加します。

ただし、 @ Dan が正しく述べているように、正しい解決策は、JARマニフェストに必要なすべてのJARのクラスパスが含まれるようにすることです。

57
toolkit

-jarオプションを省略して、次のようにjarファイルを開始できます。

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

29
g_tom

これが発生している問題です。

jARファイルが「C:\ Java\apps\appli.jar」からロードされ、マニフェストファイルにClass-Path:参照「lib/other.jar」がある場合、クラスローダーは「C:\ Java」を検索します。 「other.jar」の場合は\ apps\lib\" JARファイルのエントリ「lib/other.jar」は参照しません。

解決策:-

  1. プロジェクトを右クリックし、エクスポートを選択します。
  2. Java Folderを選択し、その中でJARファイルの代わりにRunnable JAR Fileを選択します。
  3. 適切なオプションを選択し、「ライブラリ処理」セクションで3番目のオプションを選択します(生成されたJARの隣のサブフォルダに必要なライブラリをコピーします)。

[[〜#〜] edit [〜#〜] = 3番目のオプションは、jarに加えて2番目のオプション(「必要なライブラリを生成されたJARにパッケージ化する」 ")は、jarファイルがあるときにも使用できます。 ]

  1. [完了]をクリックすると、マニフェストファイルに記載されているJARを含むフォルダーとともに、指定した位置にJARが作成されます。
  2. ターミナルを開き、jarへの適切なパスを指定し、このコマンドを使用して実行しますJava -jar abc.jar

    これで、クラスローダーは、アプリケーションJARを含む同じフォルダーに存在するため、参照されたJARの正しいフォルダーを検索します。「Java.lang.NoClassDefFoundError」例外はスローされません。

これは私のために働いた...それもあなたのために働くことを願っています!!!

18

プログラムで外部ライブラリを使用し、jarファイルにまとめてパックしようとすると、クラスパスの問題などのため、それほど単純ではありません。

この問題には OneJar を使用したいと思います。

3
flash

私は私の瓶と同じ問題を抱えていました

  1. MANIFEST.MFファイルを作成します。

マニフェストバージョン:1.0

密閉済み:true

クラスパス:。 lib/jarX1.jar lib/jarX2.jar lib/jarX3.jar

メインクラス:com.MainClass

  1. プロジェクトを右クリックし、エクスポートを選択します。

チェックしたプロジェクトのすべてのoutpoutフォルダーをエクスポートを選択します

  1. ワークスペースから既存のマニフェストを使用して選択し、MANIFEST.MFファイルを選択します

これは私のために働いた:)

2
mouhcine

マニフェストを使用しているときに、クラスパスのjarのリストには、各jarのリストの後にスペースが必要であることがわかりました。 「required_lib/Sun/pop3.jar required_lib/Sun/smtp.jar」。リストの最後であっても。

0
Mary C