web-dev-qa-db-ja.com

NoClassDefFoundErrorとClassNotFoundExceptionの違いは何ですか?また、その原因は何ですか?

NoClassDefFoundErrorClassNotFoundExceptionの違いは何ですか?

何が投げられるのですか?どうすれば解決できますか。

新しいjarファイルを含めるために既存のコードを修正するとき、私はこれらのthrowablesにしばしば遭遇します。私はWebStartを通して配布されたJavaアプリのためにクライアント側とサーバー側の両方でそれらをヒットしました。

私が遭遇した考えられる理由:

  1. コードのクライアント側でbuild.xmlに含まれていないパッケージ
  2. 使用している新しいjarファイルにランタイムクラスパスがありません
  3. 以前のjarとバージョンが競合しています

私が今日これらに遭遇したとき、私は物事を動かすために試行錯誤のアプローチを取ります。もっと明快さと理解が必要です。

358
krisp

Java API仕様との違いは以下のとおりです。

ClassNotFoundException の場合:

アプリケーションが文字列名を使用してクラスにロードしようとしたときにスローされます。

  • クラスforNameClassメソッド。
  • クラスfindSystemClassClassLoaderメソッド。
  • クラスloadClassClassLoaderメソッド。

しかし、指定された名前のクラスの定義が見つかりませんでした。

NoClassDefFoundError の場合:

Java仮想マシンまたはClassLoaderインスタンスが(通常のメソッド呼び出しの一部として、または新しい式を使用した新しいインスタンスの作成の一部として)クラスの定義をロードしようとし、クラスの定義が見つからなかった場合にスローされます。

検索対象のクラス定義は、現在実行中のクラスがコンパイルされたときに存在していましたが、その定義はもう見つかりません。

そのため、ソースが正常にコンパイルされたときにNoClassDefFoundErrorが発生しますが、実行時には必要なclassファイルが見つかりませんでした。これは、JARファイルの配布または作成時に発生する可能性があり、必要なすべてのclassファイルが含まれているわけではありません。

ClassNotFoundExceptionについては、実行時にクラスへのリフレクティブな呼び出しを試みることから生じる可能性がありますが、プログラムが呼び出そうとしているクラスは存在しません。

両者の違いは、一方がErrorであり、もう一方がExceptionであることです。 NoClassDefFoundErrorErrorであり、Java Virtual Machineが期待するクラスを見つけるのに問題があるために発生します。 classファイルが見つからないか、コンパイル時に生成または検出されたものと同じではないため、コンパイル時に動作すると予想されるプログラムを実行できません。 JVMからプログラムを起動できないため、これは非常に重大なエラーです。

一方、ClassNotFoundExceptionExceptionなので、やや予想されるものであり、回復可能なものです。リフレクションを使用するとエラーが発生しやすくなります(期待通りに動作しないことが予想されるため、必要なクラスがすべて存在することを確認するコンパイル時チェックがないため、目的のクラスの検索に関する問題は実行時に表示されます) 。

380
coobird

報告されたクラスがClassLoaderによって見つからない場合は、ClassNotFoundExceptionがスローされます。これは通常、クラスがCLASSPATHから欠落していることを意味します。また、問題のクラスが、親クラスローダにロードされた別のクラスからロードされようとしているため、子クラスローダのクラスが表示されないことも考えられます。これは、App Serverのようなより複雑な環境で作業している場合には時々起こります(WebSphereはそのようなクラスローダーの問題で悪名高いです)。

Java.lang.NoClassDefFoundErrorJava.lang.ClassNotFoundExceptionを混同する傾向がありますが、重要な違いがあります。例えば、次のような例外(Java.lang.NoClassDefFoundErrorはJava.lang.Errorのサブクラスなので、実際にはエラーです)

Java.lang.NoClassDefFoundError:
org/Apache/activemq/ActiveMQConnectionFactory

activeMQConnectionFactoryクラスがCLASSPATHにないという意味ではありません。正反対のことを言ってください。つまり、クラスActiveMQConnectionFactoryはClassLoaderによって検出されましたが、クラスをロードしようとしたときに、クラス定義の読み取り中にエラーが発生しました。これは通常、問題のクラスにClassLoaderによって検出されないクラスを使用する静的ブロックまたはメンバーがある場合に発生します。そのため、問題の原因を特定するには、問題のクラスのソース(この場合はActiveMQConnectionFactory)を表示し、静的ブロックまたは静的メンバーを使用してコードを探します。ソースにアクセスできない場合は、JADを使用してそれを逆コンパイルしてください。

コードを調べて、以下のようなコード行を見つけたとしましょう。あなたのCLASSPATHにSomeClassクラスがあることを確認してください。

private static SomeClass foo = new SomeClass();

ヒント:クラスがどのjarに属しているかを調べるには、WebサイトのjarFinderを使用できます。これにより、ワイルドカードを使用してクラス名を指定することができ、jarファイルのデータベースでクラスを検索します。 jarhooはあなたが同じことをすることを可能にしますが、それはもう自由に使用できません。

クラスがどのjarに属するのかをローカルパスで見つけたい場合は、jarscan( http://www.inetfeedback.com/jarscan/ )のようなユーティリティを使用できます。探したいクラスと、jarファイルとZipファイルでクラスの検索を開始するルートディレクトリのパスを指定するだけです。

80
Sanjiv Jivan

NoClassDefFoundErrorは基本的にリンケージエラーです。それはあなたが(静的に "new"で)オブジェクトをインスタンス化しようとした時に起こり、それがコンパイル中だった時には見つかりません。

ClassNotFoundExceptionはより一般的であり、存在しないクラスを使用しようとしたときのランタイム例外です。たとえば、関数にパラメータを設定してそのインタフェースを受け入れ、そのインタフェースを実装するクラスを他の人に渡しても、そのクラスにアクセスできない場合などです。 loadClass()やClass.forName()の使用など、動的クラスローディングのケースもカバーしています。

33
cletus

NoClassDefFoundError(NCDFE)は、コードが "new Y()"を実行したときに発生し、Yクラスが見つかりません。

他のコメントが示すように、単にYがクラスローダーから欠落している可能性がありますが、Yクラスが署名されていないか無効なシグニチャーを持っている、またはYがコードから見えない別のクラスローダーによってロードされている可能性があります。あるいは、YがZに依存している場合でも、Zは上記のいずれの理由でもロードできませんでした。

この場合、JVMはX(NCDFE)をロードした結果を記憶し、Yを要求するたびに新しいNCDFEをスローします。理由はわかりません。

クラスa [{a。静的クラスb {} 
 public static void main(String args []){
 System.out.println( "最初の試みnew b (): "); 
 {new b();を試してください。 } catch(Throwable t){t.printStackTrace();} 
 System.out.println( "\ n 2回目のnew b():"); 
 try {new b();} } catch(Throwable t){t.printStackTrace();} 
} 
} 

これをa.Javaという名前で保存してください

コードは単に新しい "b"クラスを2回インスタンス化しようとしますが、それ以外はバグがなく、また何もしません。

javac a.Javaを使用してコードをコンパイルしてから、Java -cp . aを呼び出してaを実行します。2行のテキストが出力されるだけで、エラーなしで正常に実行されます。

それから、 "a $ b.class"ファイルを削除して(あるいは、ゴミでいっぱいにするか、あるいはその上にa.classをコピーして)、欠けているか壊れたクラスをシミュレートします。これが起こるのです:

最初に新しいb()を試みてください:
 Java.lang.NoClassDefFoundError:a.main(a.Java:5)でのa $ b 
 [.____。原因: Java.lang.ClassNotFoundException:a Java.net.URLClassLoaderで$ b 
 $ 1.run(URLClassLoader.Java:200)
 Java.security.AccessController.doPrivileged(ネイティブメソッド)[.____ Java.net.URLClassLoader.findClass(URLClassLoader.Java:188)
 Java.lang.ClassLoader.loadClass(ClassLoader.Java:307)
 Sun.misc.Launcher $ AppClassLoader .loadClass(Launcher.Java:301)
 at Java.lang.ClassLoader.loadClass(ClassLoader.Java:252)
 at Java.lang.ClassLoader.loadClassInternal(ClassLoader.Java:320)[ [1]新しいb()の2回目の試み:
 Java.lang.NoClassDefFoundError:a.mainでa $ b 
 a.Java:7)

最初の呼び出しではClassNotFoundException(クラスが見つからないときにクラスローダーによってスローされます)が発生します。これは、問題のコード(new b())が正常に機能するため、チェックなしのNoClassDefFoundErrorでラップする必要があります。

2番目の試みももちろん失敗しますが、ClassLoaderは失敗したクラスローダーを覚えているように見えるため、ラップされた例外はもう発生しません。あなたはNCDFEだけを見て、実際に何が起こったのかについて全く手がかりを知りません。

そのため、根本的な原因がないNCDFEを見たことがある場合は、エラーの原因を見つけるためにクラスがロードされた最初の時間まで追跡できるかどうかを確認する必要があります。

29
mogsie

http://www.javaroots.com/2013/02/classnotfoundexception-vs.html から:

ClassNotFoundException:クラスローダーがクラスパスで必要なクラスを見つけられなかった場合に発生します。そのため、基本的にはクラスパスを確認してクラスパスにクラスを追加する必要があります。

NoClassDefFoundError:これはデバッグが難しく、その理由を見つけるのが難しくなります。これはコンパイル時に必要なクラスが存在するが、実行時にクラスが変更または削除された場合、またはクラスの静的初期化が例外をスローした場合にスローされます。これは、ロードされているクラスがクラスパスに存在することを意味しますが、このクラスに必要なクラスの1つが削除されるか、コンパイラによってロードされませんでした。それで、あなたはこのクラスに依存しているクラスを見るべきです。

public class Test1
{
}


public class Test 
{
   public static void main(String[] args)
   {
        Test1 = new Test1();    
   }

}

両方のクラスをコンパイルした後、Test1.classファイルを削除してTest classを実行すると、スローされます。

Exception in thread "main" Java.lang.NoClassDefFoundError: Test
    at Test1.main(Test1.Java:5)
Caused by: Java.lang.ClassNotFoundException: Test
    at Java.net.URLClassLoader$1.run(Unknown Source)
    at Java.net.URLClassLoader$1.run(Unknown Source)
    at Java.security.AccessController.doPrivileged(Native Method)
    at Java.net.URLClassLoader.findClass(Unknown Source)
    at Java.lang.ClassLoader.loadClass(Unknown Source)
    at Sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
    at Java.lang.ClassLoader.loadClass(Unknown Source)
    ... 1 more

ClassNotFoundException:アプリケーションがその名前でクラスをロードしようとしたが、指定された名前のクラスの定義が見つからなかった場合にスローされます。

NoClassDefFoundError:Java仮想マシンがクラスの定義をロードしようとしてクラスの定義が見つからない場合にスローされます。

19
KingFeming

それらのそれぞれを取得する理由とそのようなエラーに対処する方法についての思考プロセスは何ですか?

それらは密接に関連しています。 ClassNotFoundExceptionは、Javaが名前で特定のクラスを探しに行き、それを正常にロードできなかったときにスローされます。 NoClassDefFoundErrorは、Javaが既存のコードにリンクされているクラスを探すときにスローされましたが、何らかの理由でそれを見つけることができなかった(例:クラスパスの誤り、Javaのバージョンの誤り、ライブラリのバージョンの誤り)。何かがひどく間違っていたことを示すので致命的です。

C言語のバックグラウンドを持っている場合、CNFEはdlopen()/dlsym()の失敗のようなもので、NCDFEはリンカの問題です。 2番目のケースでは、関係するクラスファイルは、実際にそれらを使用しようとしている設定でコンパイルされていないはずです。

15
Donal Fellows

例1:

class A{
 void met(){
   Class.forName("com.example.Class1");
 }
}

com/example/Class1がどのクラスパスにも存在しない場合は、ClassNotFoundExceptionがスローされます。

例2:

Class B{
  void met(){
   com.example.Class2 c = new com.example.Class2();
 }
}

Bのコンパイル中にcom/example/Class2が存在したが、実行中に見つからなかった場合は、NoClassDefFoundErrorがスローされます。

どちらも実行時例外です。

11
Dinesh

ClassNotFoundException Stringで参照してクラスをロードしようとしたときにスローされます。たとえば、Class.forName()のパラメータはStringです。これにより、無効なバイナリ名がクラスローダに渡される可能性があります。

ClassNotFoundExceptionは、無効なバイナリ名が検出された場合にスローされます。たとえば、クラス名に '/'文字が含まれていると、ClassNotFoundExceptionが発生します。直接参照されているクラスがクラスパスで利用できない場合にもスローされます。

一方、 NoClassDefFoundError がスローされます

  • クラスの実際の物理表現 - .classファイルが利用できない場合 -
  • または、クラスがすでに別のクラスローダにロードされている(通常、親クラスローダがそのクラスをロードしているため、そのクラスを再度ロードすることはできません)。
  • または互換性のないクラス定義が見つかった場合 - クラスファイル内の名前が要求された名前と一致しません。
  • または(最も重要なこととして)依存クラスを見つけてロードできない場合この場合、直接参照されているクラスが見つかってロードされた可能性がありますが、従属クラスが使用不可であるかロードできません。これは、直接参照されるクラスがClass.forNameまたは同等のメソッドを介してロードできるシナリオです。これはリンケージの失敗を示します。

手短に言うと、クラスローダがクラス定義を見つけられないかロードできない場合(ClassNotFoundExceptionのためのクラスの文字列ベースのロードとは対照的に)、NoClassDefFoundErrorは通常new()ステートメントまたはメソッド呼び出しの前に存在しないクラスをロードするときにスローされます。 s).

最終的には、クラスをロードできないときにClassNotFoundExceptionのインスタンスをスローするのはClassLoaderの実装次第です。ほとんどのカスタムクラスローダの実装はURLClassLoaderを拡張するのでこれを実行します。通常、クラスローダーは、どのメソッド実装に対しても明示的にNoClassDefFoundErrorをスローしません。この例外は通常、クラスローダー自体ではなく、HotSpotコンパイラのJVMからスローされます。

9
Vineet Reynolds

ClassNotFoundExceptionとNoClassDefFoundErrorの違い

enter image description here

8
Lawakush Kurmi

名前そのものを使えば、Exceptionから簡単に識別でき、もう1つはErrorから簡単に識別できます。

Exception: programの実行中に例外が発生しました。プログラマはtry catchブロックによってこれらの例外を処理できます。 2種類の例外があります。コンパイル時にスローされるチェック済みの例外。実行時にスローされるランタイム例外。これらの例外は通常、プログラミングが不適切なために発生します。

Error:これらはまったく例外ではなく、プログラマの範囲を超えています。これらのエラーは通常JVMによってスローされます。


enter image description here画像のソース

違い:

ClassNotFoundException:

  • クラスローダーが失敗するverifyクラスバイトコードLink phase of class loading subsystemClassNotFoundExceptionが返される。
  • ClassNotFoundExceptionJava.lang.Exceptionクラスから直接派生したチェック済みの例外であり、明示的な処理を提供する必要があります。
  • ClassLoader.loadClass()、Class.forName()およびClassLoader.findSystemClass()を使用して実行時にクラスの名前を提供することで、クラスの明示的なロードが含まれる場合、ClassNotFoundExceptionが呼び出されます。

NoClassDefFoundError:

  • クラスローダーが失敗する解決クラス内の参照リンクフェーズ of クラスローディングサブシステムNoClassDefFoundErrorを取得しました。
  • NoClassDefFoundErrorLinkageErrorクラスから派生したErrorです。これは、エラーが発生した場合を示すために使用されます。クラスは他のクラスに依存しており、コンパイル後にそのクラスは互換性がなくなります。
  • NoClassDefFoundErrorは、そのクラスからのメソッド呼び出しまたは任意の変数アクセスのため、クラスの暗黙的な読み込みの結果です。

類似点:

  • NoClassDefFoundErrorClassNotFoundExceptionはどちらも、実行時にクラスが利用できないことに関連しています。
  • ClassNotFoundExceptionNoClassDefFoundErrorはどちらもJavaクラスパスに関連しています。
7
Premraj

クラスローダーのスーパーシステムアクションを考えます。

http://www.artima.com/insidejvm/ed2/images/fig7-1.gif

これは違いを理解するのに役立ちました。 http://docs.Oracle.com/javase/specs/jvms/se7/html/jvms-5.html

クラスのロード中にエラーが発生した場合、LinkageErrorというサブクラスのインスタンスを、ロード中のクラスまたはインタフェースを(直接的または間接的に)使用しているプログラムのある時点でスローする必要があります。

Java仮想マシンが検証中(5.4.1)または解決中(5.4.3)(ただし初期化(5.5)ではない)にクラスCをロードしようとした場合、およびCのロードを開始するために使用されるクラスローダClassNotFoundExceptionのインスタンスをスローし、Java仮想マシンはNoClassDefFoundErrorのインスタンスをスローする必要があります。この原因はClassNotFoundExceptionのインスタンスです。

したがって、ClassNotFoundExceptionNoClassDefFoundErrorの根本的な原因です。
そして、aNoClassDefFoundErrorは、型ロードエラーの特殊なケースで、Linkingステップで発生します。

3

実際に考えられる理由を1つ追加します。

  • ClassNotFoundException:クレタスが言ったように、継承されたインターフェースのクラスがクラスパスにない間にインターフェースを使用します。たとえば、Service Provider Pattern(または Service Locator )が存在しないクラスを探します。
  • NoClassDefFoundError:指定クラスの依存関係が見つからないのに指定クラスが見つかりました

実際には、Errorが静かにスローされます静かに、例えばタイマータスクを送信すると、タイマータスクでそれがスローされますエラー、ほとんどの場合、プログラムはキャッチするだけです例外。そしてTimerメインループは何の情報もなしに終了します。 NoClassDefFoundErrorに似たエラーは、静的初期化子または静的変数の初期化子が例外を投げるときの ExceptionInInitializerError です。

2
leef

ClassNotFoundExceptionは、Class.forName()またはClassLoader.findSystemClass()を使用してクラスをその文字列名でロードするようJVMに指示したときに発生するチェック済みの例外です。 ClassLoader.loadClass()メソッドと上記のクラスがクラスパスに見つかりません。

ほとんどの場合、クラスパスを必要なJARファイルで更新せずにアプリケーションを実行しようとすると、この例外が発生します。たとえば、JDBCコードを使用してデータベース、つまりMySQLに接続するときにこの例外が発生した可能性がありますが、クラスパスにJARがありません。

NoClassDefFoundErrorエラーが(通常のメソッド呼び出しの一部として、または作成の一部として)コード実行の一部である特定のクラスをJVMがロードしようとすると発生しますnewキーワードを使用したインスタンスとそのクラスはクラスパスには存在しませんが、プログラムを実行するにはそれをコンパイルする必要があり、存在しないクラスを使用しようとするとコンパイルが行われるため、コンパイル時に存在します。エラー。

以下は簡単な説明です

enter image description here

詳しくは、 ClassNotFoundExceptionとNoClassDefFoundErrorのすべてについて を参照してください。

1
Naresh Joshi

リフレッシュする必要があるときは、次のことを繰り返し思い出します。

ClassNotFoundException

クラス階層

ClassNotFoundException extends ReflectiveOperationException extends Exception extends Throwable

デバッグ中

  1. 必要なjarファイル、クラスがクラスパスにありません。
  2. 必要なjarファイルがすべてjvmのクラスパスにあることを確認してください。

NoClassDefFoundError

クラス階層

NoClassDefFoundError extends LinkageError  extends Error extends Throwable

デバッグ中

  1. 正しくコンパイルされた、クラスを動的にロードする際の問題
  2. 静的ブロック、コンストラクタ、従属クラスのinit()メソッドの問題、そして実際のエラーは複数のレイヤでラップされています[特にspringを使うと、hibernateは実際の例外がラップされ、NoClassDefErrorが返されます]。
  3. 依存クラスの静的ブロックの下で "ClassNotFoundException"が発生した場合
  4. クラスのバージョンに問題があります。これは、同じクラスの2つのバージョンv1、v2が異なるjar /パッケージの下にあり、それらがv1を使用して正常にコンパイルされ、関連メソッド/ varsがないランタイムにロードされた場合に発生します。 [私はかつてクラスパスに現れた複数のjarファイルの下のlog4j関連クラスの重複を削除することでこの問題を解決しました]
1
147.3k

ClassNotFoundExceptionとNoClassDefFoundErrorは、実行時に特定のクラスが見つからなかった場合に発生します。ただし、これらは異なるシナリオで発生します。

ClassNotFoundExceptionは、Class.forName()またはloadClass()メソッドを使用して実行時にクラスをロードしようとしたときに、クラスパスにクラスが見つからなかった場合に発生する例外です。

    public class MainClass
    {
        public static void main(String[] args)
        {
            try
            {
                Class.forName("Oracle.jdbc.driver.OracleDriver");
            }catch (ClassNotFoundException e)
            {
                e.printStackTrace();
            }
        }
    }



    Java.lang.ClassNotFoundException: Oracle.jdbc.driver.OracleDriver
    at Java.net.URLClassLoader.findClass(Unknown Source)
    at Java.lang.ClassLoader.loadClass(Unknown Source)
    at Sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
    at Java.lang.ClassLoader.loadClass(Unknown Source)
    at Java.lang.Class.forName0(Native Method)
    at Java.lang.Class.forName(Unknown Source)
    at pack1.MainClass.main(MainClass.Java:17)

NoClassDefFoundErrorは、コンパイル時に特定のクラスが存在していても実行時に見つからなかった場合に発生するエラーです。

    class A
    {
      // some code
    }
    public class B
    {
        public static void main(String[] args)
        {
            A a = new A();
        }
    }

上記のプログラムをコンパイルすると、2つの.classファイルが生成されます。 1つはA.class、もう1つはB.classです。 A.classファイルを削除してB.classファイルを実行すると、Java Runtime Systemは次のようにNoClassDefFoundErrorをスローします。

    Exception in thread "main" Java.lang.NoClassDefFoundError: A
    at MainClass.main(MainClass.Java:10)
    Caused by: Java.lang.ClassNotFoundException: A
    at Java.net.URLClassLoader.findClass(URLClassLoader.Java:381)
    at Java.lang.ClassLoader.loadClass(ClassLoader.Java:424)
    at Sun.misc.Launcher$AppClassLoader.loadClass(Launcher.Java:331)
    at Java.lang.ClassLoader.loadClass(ClassLoader.Java:357)
0
Neeraj Gahlawat