384

NoClassDefFoundErrorとの違いは何ClassNotFoundExceptionですか?

それらが投げられる原因は何ですか?それらはどのように解決できますか?

新しいjarファイルを含めるように既存のコードを変更するときに、これらのスローアブルに遭遇することがよくあります。Webstartを介して配布されるJavaアプリについて、クライアント側とサーバー側の両方でヒットしました。

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

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

今日これらに遭遇したとき、私は物事を機能させるためにトレイルアンドエラーアプローチを取ります。もっと明確に理解する必要があります。

4

15 に答える 15

392

JavaAPI仕様との違いは次のとおりです。

の場合ClassNotFoundException

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

  • forNameクラスのメソッドClass
  • findSystemClassクラスのメソッドClassLoader
  • loadClassクラスのメソッドClassLoader

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

の場合NoClassDefFoundError

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

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

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

についてClassNotFoundExceptionは、実行時にクラスにリフレクティブ呼び出しを行おうとしたことが原因のようですが、プログラムが呼び出そうとしているクラスは存在しません。

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

一方、ClassNotFoundExceptionはであるExceptionため、ある程度期待されており、回復可能なものです。リフレクションを使用すると、エラーが発生しやすくなります(期待どおりに進まない可能性があるためです。必要なクラスがすべて存在することを確認するコンパイル時のチェックがないため、目的のクラスを見つける際の問題は実行時に発生します。 。

于 2009-09-22T02:37:19.330 に答える
83

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

java.lang.NoClassDefFoundError人々は混同しがちjava.lang.ClassNotFoundExceptionですが、重要な違いがあります。たとえば、次のような例外 (実際java.lang.NoClassDefFoundErrorには java.lang.Error のサブクラスであるため、エラー)

java.lang.NoClassDefFoundError:
org/apache/activemq/ActiveMQConnectionFactory

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

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

private static SomeClass foo = new SomeClass();

ヒント : クラスが属する jar を見つけるには、Web サイト jarFinder を使用できます。これにより、ワイルドカードを使用してクラス名を指定でき、jar のデータベースでクラスが検索されます。jarhoo でも同じことができますが、無料では使用できなくなりました。

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

于 2010-02-06T14:55:55.113 に答える
37

NoClassDefFoundError基本的にリンケージエラーです。これは、オブジェクトを(静的に「new」で)インスタンス化しようとしたときに発生し、コンパイル中は見つかりませんでした。

ClassNotFoundExceptionより一般的であり、存在しないクラスを使用しようとすると実行時の例外になります。たとえば、関数にパラメータがあり、インターフェイスを受け入れ、誰かがそのインターフェイスを実装するクラスを渡しますが、クラスにアクセスできません。loadClass()また、またはを使用するなど、動的なクラス読み込みの場合についても説明しClass.forName()ます。

于 2009-09-22T02:36:57.317 に答える
30

NoClassDefFoundError (NCDFE) は、コードが "new Y()" を実行し、Y クラスが見つからない場合に発生します。

他のコメントが示唆するように、Yがクラスローダーにないだけかもしれませんが、Yクラスが署名されていないか無効な署名があるか、コードに表示されない別のクラスローダーによってYがロードされている可能性があります、または Y が上記のいずれかの理由でロードできなかった Z に依存していることさえあります。

これが発生した場合、JVM は X をロードした結果 (NCDFE) を記憶し、Y を要求するたびに、理由を説明せずに単に新しい NCDFE をスローします。

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

これを a.java としてどこかに保存します

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

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

次に、「a$b.class」ファイルを削除 (または、ガベージで埋めるか、a.class をその上にコピー) して、欠落または破損したクラスをシミュレートします。何が起こるかは次のとおりです。

最初の試行 new b():
java.lang.NoClassDefFoundError: a$b
    a.main(a.java:5)
原因: java.lang.ClassNotFoundException: a$b
    java.net.URLClassLoader$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) で
    java.lang.ClassLoader.loadClass(ClassLoader.java:252) で
    java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320)で
    ... あともう1つ

2 回目の試行 new b():
java.lang.NoClassDefFoundError: a$b
    a.main(a.java:7) で

最初の呼び出しで ClassNotFoundException (クラスが見つからない場合にクラス ローダーによってスローされる) が発生します。この例外は、未チェックの NoClassDefFoundError でラップする必要がありますnew b()

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

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

于 2010-07-07T20:21:48.213 に答える
15

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

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

C のバックグラウンドがある場合、CNFE はdlopen()/の失敗のようなものでdlsym()あり、NCDFE はリンカーの問題です。2 番目のケースでは、関連するクラス ファイルは、使用しようとしている構成で実際にコンパイルされていないはずです。

于 2010-07-07T21:04:07.330 に答える
11

例 #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();
 }
}

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

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

于 2015-01-12T17:31:01.267 に答える
9

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

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

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

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

つまり、NoClassDefFoundErrorは通常、クラスローダーがクラス定義( s)。

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

于 2009-09-22T03:22:09.530 に答える
9

ClassNotFoundException と NoClassDefFoundError の違い

ここに画像の説明を入力

于 2016-01-31T19:15:58.017 に答える
9

Exception名前自体で、一方が からのもので、もう一方が からのものであることを簡単に識別できますError

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

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


ここに画像の説明を入力 画像ソース

違い:

ClassNotFoundException:

  • クラス ローダーは、 Linkingでバイト コードを検証できません。
  • ClassNotFoundExceptionアプリケーションが完全修飾名を使用してクラスをロードしようとしたときに、クラスパスでその定義が見つからない場合に発生するチェック例外です。
  • ClassNotFoundExceptionClassLoader.loadClass()、Class.forName()、および ClassLoader.findSystemClass() を使用して実行時にクラスの名前を指定することにより、クラスの明示的なロードが関係している場合に表示されます。

NoClassDefFoundError:

  • クラス ローダーは、 Linkingでのクラスの参照の解決に失敗します。
  • NoClassDefFoundErrorクラスから派生したエラーLinkageErrorであり、致命的なエラーです。new キーワードを使用してクラスをインスタンス化するか、メソッド呼び出しでクラスをロードしようとしているときに、JVM がクラスの定義を見つけられない場合に発生します。
  • NoClassDefFoundErrorそのクラスからのメソッド呼び出しまたは変数アクセスによるクラスの暗黙的なロードの結果です。

類似点:

  • NoClassDefFoundErrorとは両方とも、ClassNotFoundException実行時にクラスを使用できないことに関連しています。
  • ClassNotFoundExceptionとの両方NoClassDefFoundErrorが Java クラスパスに関連しています。
于 2015-12-30T01:00:03.817 に答える
2

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

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

実際には、Errorはサイレントにスローされる場合があります。たとえば、タイマー タスクを送信すると、タイマー タスクでErrorがスローされますが、ほとんどの場合、プログラムはExceptionのみをキャッチします。その後、タイマーのメイン ループは何の情報もなく終了します。NoClassDefFoundError と同様のエラーは、静的初期化子または静的変数の初期化子が例外をスローした場合の ExceptionInInitializerError です

于 2012-02-17T04:36:52.097 に答える