NoClassDefFoundError
とClassNotFoundException
の違いは何ですか?
何が投げられるのですか?どうすれば解決できますか。
新しいjarファイルを含めるために既存のコードを修正するとき、私はこれらのthrowablesにしばしば遭遇します。私はWebStartを通して配布されたJavaアプリのためにクライアント側とサーバー側の両方でそれらをヒットしました。
私が遭遇した考えられる理由:
build.xml
に含まれていないパッケージ私が今日これらに遭遇したとき、私は物事を動かすために試行錯誤のアプローチを取ります。もっと明快さと理解が必要です。
Java API仕様との違いは以下のとおりです。
アプリケーションが文字列名を使用してクラスにロードしようとしたときにスローされます。
- クラス
forName
のClass
メソッド。- クラス
findSystemClass
のClassLoader
メソッド。- クラス
loadClass
のClassLoader
メソッド。しかし、指定された名前のクラスの定義が見つかりませんでした。
NoClassDefFoundError
の場合:
Java仮想マシンまたは
ClassLoader
インスタンスが(通常のメソッド呼び出しの一部として、または新しい式を使用した新しいインスタンスの作成の一部として)クラスの定義をロードしようとし、クラスの定義が見つからなかった場合にスローされます。検索対象のクラス定義は、現在実行中のクラスがコンパイルされたときに存在していましたが、その定義はもう見つかりません。
そのため、ソースが正常にコンパイルされたときにNoClassDefFoundError
が発生しますが、実行時には必要なclass
ファイルが見つかりませんでした。これは、JARファイルの配布または作成時に発生する可能性があり、必要なすべてのclass
ファイルが含まれているわけではありません。
ClassNotFoundException
については、実行時にクラスへのリフレクティブな呼び出しを試みることから生じる可能性がありますが、プログラムが呼び出そうとしているクラスは存在しません。
両者の違いは、一方がError
であり、もう一方がException
であることです。 NoClassDefFoundError
はError
であり、Java Virtual Machineが期待するクラスを見つけるのに問題があるために発生します。 class
ファイルが見つからないか、コンパイル時に生成または検出されたものと同じではないため、コンパイル時に動作すると予想されるプログラムを実行できません。 JVMからプログラムを起動できないため、これは非常に重大なエラーです。
一方、ClassNotFoundException
はException
なので、やや予想されるものであり、回復可能なものです。リフレクションを使用するとエラーが発生しやすくなります(期待通りに動作しないことが予想されるため、必要なクラスがすべて存在することを確認するコンパイル時チェックがないため、目的のクラスの検索に関する問題は実行時に表示されます) 。
報告されたクラスが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を使用してそれを逆コンパイルしてください。
コードを調べて、以下のようなコード行を見つけたとしましょう。あなたのCLASSPATHにSomeClassクラスがあることを確認してください。
private static SomeClass foo = new SomeClass();
ヒント:クラスがどのjarに属しているかを調べるには、WebサイトのjarFinderを使用できます。これにより、ワイルドカードを使用してクラス名を指定することができ、jarファイルのデータベースでクラスを検索します。 jarhooはあなたが同じことをすることを可能にしますが、それはもう自由に使用できません。
クラスがどのjarに属するのかをローカルパスで見つけたい場合は、jarscan( http://www.inetfeedback.com/jarscan/ )のようなユーティリティを使用できます。探したいクラスと、jarファイルとZipファイルでクラスの検索を開始するルートディレクトリのパスを指定するだけです。
NoClassDefFoundErrorは基本的にリンケージエラーです。それはあなたが(静的に "new"で)オブジェクトをインスタンス化しようとした時に起こり、それがコンパイル中だった時には見つかりません。
ClassNotFoundExceptionはより一般的であり、存在しないクラスを使用しようとしたときのランタイム例外です。たとえば、関数にパラメータを設定してそのインタフェースを受け入れ、そのインタフェースを実装するクラスを他の人に渡しても、そのクラスにアクセスできない場合などです。 loadClass()やClass.forName()の使用など、動的クラスローディングのケースもカバーしています。
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を見たことがある場合は、エラーの原因を見つけるためにクラスがロードされた最初の時間まで追跡できるかどうかを確認する必要があります。
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仮想マシンがクラスの定義をロードしようとしてクラスの定義が見つからない場合にスローされます。
それらのそれぞれを取得する理由とそのようなエラーに対処する方法についての思考プロセスは何ですか?
それらは密接に関連しています。 ClassNotFoundException
は、Javaが名前で特定のクラスを探しに行き、それを正常にロードできなかったときにスローされます。 NoClassDefFoundError
は、Javaが既存のコードにリンクされているクラスを探すときにスローされましたが、何らかの理由でそれを見つけることができなかった(例:クラスパスの誤り、Javaのバージョンの誤り、ライブラリのバージョンの誤り)。何かがひどく間違っていたことを示すので致命的です。
C言語のバックグラウンドを持っている場合、CNFEはdlopen()
/dlsym()
の失敗のようなもので、NCDFEはリンカの問題です。 2番目のケースでは、関係するクラスファイルは、実際にそれらを使用しようとしている設定でコンパイルされていないはずです。
例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
がスローされます。
どちらも実行時例外です。
ClassNotFoundException Stringで参照してクラスをロードしようとしたときにスローされます。たとえば、Class.forName()のパラメータはStringです。これにより、無効なバイナリ名がクラスローダに渡される可能性があります。
ClassNotFoundExceptionは、無効なバイナリ名が検出された場合にスローされます。たとえば、クラス名に '/'文字が含まれていると、ClassNotFoundExceptionが発生します。直接参照されているクラスがクラスパスで利用できない場合にもスローされます。
一方、 NoClassDefFoundError がスローされます
手短に言うと、クラスローダがクラス定義を見つけられないかロードできない場合(ClassNotFoundExceptionのためのクラスの文字列ベースのロードとは対照的に)、NoClassDefFoundErrorは通常new()ステートメントまたはメソッド呼び出しの前に存在しないクラスをロードするときにスローされます。 s).
最終的には、クラスをロードできないときにClassNotFoundExceptionのインスタンスをスローするのはClassLoaderの実装次第です。ほとんどのカスタムクラスローダの実装はURLClassLoaderを拡張するのでこれを実行します。通常、クラスローダーは、どのメソッド実装に対しても明示的にNoClassDefFoundErrorをスローしません。この例外は通常、クラスローダー自体ではなく、HotSpotコンパイラのJVMからスローされます。
名前そのものを使えば、
Exception
から簡単に識別でき、もう1つはError
から簡単に識別できます。
Exception: programの実行中に例外が発生しました。プログラマはtry catchブロックによってこれらの例外を処理できます。 2種類の例外があります。コンパイル時にスローされるチェック済みの例外。実行時にスローされるランタイム例外。これらの例外は通常、プログラミングが不適切なために発生します。
Error:これらはまったく例外ではなく、プログラマの範囲を超えています。これらのエラーは通常JVMによってスローされます。
違い:
ClassNotFoundException:
ClassNotFoundException
が返される。ClassNotFoundException
はJava.lang.Exception
クラスから直接派生したチェック済みの例外であり、明示的な処理を提供する必要があります。ClassNotFoundException
が呼び出されます。NoClassDefFoundError:
NoClassDefFoundError
を取得しました。NoClassDefFoundError
はLinkageError
クラスから派生したErrorです。これは、エラーが発生した場合を示すために使用されます。クラスは他のクラスに依存しており、コンパイル後にそのクラスは互換性がなくなります。NoClassDefFoundError
は、そのクラスからのメソッド呼び出しまたは任意の変数アクセスのため、クラスの暗黙的な読み込みの結果です。類似点:
NoClassDefFoundError
とClassNotFoundException
はどちらも、実行時にクラスが利用できないことに関連しています。ClassNotFoundException
とNoClassDefFoundError
はどちらもJavaクラスパスに関連しています。クラスローダーのスーパーシステムアクションを考えます。
これは違いを理解するのに役立ちました。 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のインスタンスです。
したがって、ClassNotFoundExceptionがNoClassDefFoundErrorの根本的な原因です。
そして、aNoClassDefFoundErrorは、型ロードエラーの特殊なケースで、Linkingステップで発生します。
実際に考えられる理由を1つ追加します。
実際には、Errorが静かにスローされます静かに、例えばタイマータスクを送信すると、タイマータスクでそれがスローされますエラー、ほとんどの場合、プログラムはキャッチするだけです例外。そしてTimerメインループは何の情報もなしに終了します。 NoClassDefFoundErrorに似たエラーは、静的初期化子または静的変数の初期化子が例外を投げるときの ExceptionInInitializerError です。
ClassNotFoundExceptionは、Class.forName()またはClassLoader.findSystemClass()を使用してクラスをその文字列名でロードするようJVMに指示したときに発生するチェック済みの例外です。 ClassLoader.loadClass()メソッドと上記のクラスがクラスパスに見つかりません。
ほとんどの場合、クラスパスを必要なJARファイルで更新せずにアプリケーションを実行しようとすると、この例外が発生します。たとえば、JDBCコードを使用してデータベース、つまりMySQLに接続するときにこの例外が発生した可能性がありますが、クラスパスにJARがありません。
NoClassDefFoundErrorエラーが(通常のメソッド呼び出しの一部として、または作成の一部として)コード実行の一部である特定のクラスをJVMがロードしようとすると発生しますnewキーワードを使用したインスタンスとそのクラスはクラスパスには存在しませんが、プログラムを実行するにはそれをコンパイルする必要があり、存在しないクラスを使用しようとするとコンパイルが行われるため、コンパイル時に存在します。エラー。
以下は簡単な説明です
詳しくは、 ClassNotFoundExceptionとNoClassDefFoundErrorのすべてについて を参照してください。
リフレッシュする必要があるときは、次のことを繰り返し思い出します。
ClassNotFoundException
クラス階層
ClassNotFoundException extends ReflectiveOperationException extends Exception extends Throwable
デバッグ中
NoClassDefFoundError
クラス階層
NoClassDefFoundError extends LinkageError extends Error extends Throwable
デバッグ中
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)