私はこのスレッドを通過しました NoClassDefFoundErrorとClassNotFoundExceptionの違いは何が原因で何ですか? これは、最大のupsを持つansの1つで、スレッド内では次のようになります:NoClassDefFoundError: "ソースが正常にコンパイルされたときにNoClassDefFoundErrorが発生したようですが、実行時に必要なクラスファイルが見つかりませんでした。これは、JARファイルの配布または生成で発生する可能性があり、必要なすべてのクラスファイルが含まれていない場合があります。
ClassNotFoundException:ClassNotFoundExceptionに関しては、それは実行時にクラスへのリフレクト呼び出しを行おうとすることから生じるように見えるかもしれませんが、プログラムが呼び出そうとしているクラス存在しません。
ちょっとした実験をしました。メインクラスクラスAを作成し、他のクラスクラス[〜#〜] b [を呼び出そうとしました〜#〜]から、正常にコンパイルされました。
次に、クラスAで呼び出されているクラスBを削除しました。Java.lang.ClassNotFoundExceptionを取得しましたが、トレッドの回答に従って、 NoClassDefFoundErrorが必要です(ソースは正常にコンパイルされましたが、実行時にクラスファイルが見つかりませんでした)誰かがスレッドのansの解釈で何が欠けているのか説明できますか?
package com.random;
public class A {
public static void main(String[] args) {
B b= new B();
}
}
package com.random;
public class B {
}
NoClassDefFoundError
Java=仮想マシンまたはClassLoaderインスタンスが(通常のメソッド呼び出しの一部として、または新しい式を使用して新しいインスタンスを作成する一部として)クラスの定義にロードしようとした場合にスローされます。クラスの定義が見つかりませんでした。
検索対象のクラス定義は、現在実行中のクラスがコンパイルされたときに存在していましたが、定義が見つかりません。
ClassNotFoundException
アプリケーションが文字列名を使用してクラスにロードしようとすると、クラスClassのforNameメソッドを使用してスローされます。クラスClassLoaderのfindSystemClassメソッド。クラスClassLoaderのloadClassメソッド。
JVM
はclass
自体を自動的に見つけることができないため、削除したclass
の定義を見つけることができないことを理解する必要があります。 ClassNotFoundException
をスローします。
この例外はruntime
で発生するため、最初にコンパイルしたかどうかに関係なく、ファイルを削除したため、ファイルが見つからず、exception
をスローしません。
NoClassDefFoundError
は実際には例外ではなく、Error
から派生したLinkageError
であり、ClassNotFoundException
はJava.lang.Exception
から直接派生することに注意してください。
再開するには、NoClassDefFoundError
はグローバルにJVM
がruntime
でcompiled
コードに従って存在するはずの何かにアクセスしようとしたが、実際には存在しないことを単に意味します存在する(またはクラスパスにない)。
ClassNotFoundExceptionを再現する例
public class ClassNotFoundExceptionExample {
private static final String CLASS_TO_LOAD = "main.Java.Utils";
public static void main(String[] args) {
try {
Class loadedClass = Class.forName(CLASS_TO_LOAD);
System.out.println("Class " + loadedClass + " found successfully!");
}
catch (ClassNotFoundException ex) {
System.err.println("A ClassNotFoundException was caught: " + ex.getMessage());
ex.printStackTrace();
}
}
}
NoClassDefFoundErrorを再現する例
単純なクラスを作成するTest
public class Test {
public Test() {
System.out.println("A new instance of the Test class was created!");
}
}
そしてクラスNoClassDefFoundErrorExample
public class NoClassDefFoundErrorExample {
private static Test test = new Test();
public static void main(String[] args) {
System.out.println("The definition of Test was found!");
}
}
次に、main
メソッドを実行するn実行可能ファイル.jar
を作成します。 Manifest.txt
内の.jar
ファイルで指定できます。
Main-Class: NoClassDefFoundErrorExample
次のコマンドを実行します
javac Test.Java
javac NoClassDefFoundErrorExample.Java
jar cfm NoClassDefFoundErrorExample.jar Manifest.txt NoClassDefFoundErrorExample.class
Java -jar NoClassDefFoundErrorExample.jar
NoClassDefFoundError
に注意してください
Exception in thread "main" Java.lang.NoClassDefFoundError: TestClass
at NoClassDefFoundErrorExample.(NoClassDefFoundErrorExample.Java:2)
Caused by: Java.lang.ClassNotFoundException: TestClass
at Java.net.URLClassLoader$1.run(URLClassLoader.Java:372)
at Java.net.URLClassLoader$1.run(URLClassLoader.Java:361)
at Java.security.AccessController.doPrivileged(Native Method)
at Java.net.URLClassLoader.findClass(URLClassLoader.Java:360)
at Java.lang.ClassLoader.loadClass(ClassLoader.Java:424)
at Sun.misc.Launcher$AppClassLoader.loadClass(Launcher.Java:308)
at Java.lang.ClassLoader.loadClass(ClassLoader.Java:357)
... 1 more
ええと... ClassNotFoundException
は、ランタイムがString
によって指定されたクラスを見つけようとするときに発生します。たとえば、Class.forName(Java.lang.String)
メソッドは文字列引数を取り、クラスを見つけようとしますこの名前。この場合、クラス名は文字列であり、実行時にのみ確認できます。ここで例外は明確に述べています...この「クラス」は見つかりません。だから...それは2つの理由で発生する可能性があります:
理由1.クラス名が有効なJavaクラスではありません(例-"Java.bang.kiting")。
// Example
Class cdef = Class.forName( "Java.bang.kiting" );
理由2.クラス名は有効なクラスでしたが、何らかの理由でjarにパッケージ化されていないか、クラスパスで解決されていません。つまり、ランタイムが知る限りでは...クラス名が間違っている可能性があります...ケース1と同様です。
// Example
Class cdef =Class.forName( "Apache.some.SomeLegitClass" );
実際のクラス参照が使用された場合のNoClassDefFoundError
は、
// example
import Apache.some.SomeLegitClass
SomeLegitClass i = (SomeLegitClass) instanceOfSomeLegitClass;
したがって、基本的にすべてが正しいですが、どういうわけかクラスはjarでパッケージ化されていません(またはより一般的には、クラスパスで解決されていません)。この場合、NoClassDefFoundError
を取得します。
ここで、ランタイムは、正常にコンパイルされたため、クラスが有効であることを認識していますが、「クラス定義」を見つけることができません。
違いは、誰がクラスのロードを要求したかによります:
ClassNotFoundException
は、コードがクラスを直接ロードしようとするとスローされます、クラスの完全修飾名を表すString
引数を渡します。Class.forName(String)
、またはClassLoader.loadClass(String)
。NoClassDefFoundError
は、JVMがクラスを間接的にロードするよう要求された場合にスローされます。NoClassDefFoundError
がスローされます。NoClassDefFoundError
は通常、ライブラリ(Guava、Gson、CommonsIOなど)を使用しているときに呼び出されます。ライブラリをプロジェクトのクラスパスに配置しましたが、一緒にエクスポートしなかった場合、アプリケーションの実行中にNoClassDefFoundError
を取得します。
NoClassDefFoundError
の入手方法:
このクラスで新しいプロジェクトを作成します。
public class A
{
public void do()
{
System.out.println("Do!");
}
}
.jar
ファイルとしてエクスポートします。
次に、別のプロジェクトを作成します。エクスポートしたjarファイルをクラスパスに追加します。
import ???.A;
public class Main
{
public static void main(String[] args)
{
A a = new A();
a.do();//NoClassDefFoundError thrown at here.
}
}
プロジェクトをエクスポートします。jarファイル(クラスA
付き)を含めないでください。新しくエクスポートされたjarファイルを実行すると、そのエラーが表示されます!
以前の回答で述べたように、NoClassDefFoundErrorは、コンパイル時にクラスが存在し、何らかの理由で実行時に使用できない場合に発生します。
追加したい別のシナリオがあり、これもNoClassDefFoundErrorを引き起こす可能性があります。
静的初期化ブロックのエラーなどの例外のためにロードに失敗したクラスをロードしようとすると、システムはExceptionInInitializerErrorをスローします。 同じクラスを(以前にロードできなかった)再度ロードしようとすると、システムはNoClassDefFoundErrorをスローします。
サンプルで見てみましょう
ClassWithStaticBlock.Java
public class ClassWithStaticBlock {
static {
int total = 1/0;
}
}
Main.Java
public class Main {
public static void main(String[] args) {
ClassWithStaticBlock cs;
try {
cs = new ClassWithStaticBlock();
}catch(Throwable e){
e.printStackTrace();
}
}
}
結果:
Java.lang.ExceptionInInitializerError
at Main.main(Main.Java:6)
at Sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at Sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.Java:39)
at Sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.Java:25)
at Java.lang.reflect.Method.invoke(Method.Java:597)
at com.intellij.rt.execution.application.AppMain.main(AppMain.Java:140)
Caused by: Java.lang.ArithmeticException: / by zero
at ClassWithStaticBlock.<clinit>(ClassWithStaticBlock.Java:7)
... 6 more
変更しましょうMain.Java
public class Main {
public static void main(String[] args) {
ClassWithStaticBlock cs;
try {
cs = new ClassWithStaticBlock();
}catch(Throwable e){
e.printStackTrace();
}
cs = new ClassWithStaticBlock(); //try to use ClassWithStaticBlock again
}
}
結果:
Java.lang.ExceptionInInitializerError
at Main.main(Main.Java:6)
at Sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at Sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.Java:39)
at Sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.Java:25)
at Java.lang.reflect.Method.invoke(Method.Java:597)
at com.intellij.rt.execution.application.AppMain.main(AppMain.Java:140)
Caused by: Java.lang.ArithmeticException: / by zero
at ClassWithStaticBlock.<clinit>(ClassWithStaticBlock.Java:7)
... 6 more
Exception in thread "Main Thread" Java.lang.NoClassDefFoundError: ClassWithStaticBlock
at Main.main(Main.Java:10)
at Sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at Sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.Java:39)
at Sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.Java:25)
at Java.lang.reflect.Method.invoke(Method.Java:597)
at com.intellij.rt.execution.application.AppMain.main(AppMain.Java:140)
ClassWithStaticBlock(以前の初期化に失敗した)を再度使用しようとすると、システムはNoClassDefFoundErrorをスローします。
JavaでNoClassDefFoundErrorが発生するのはなぜですか? からサンプルを見つけました
1)ClassNotFoundException
Class.forName()
またはClassLoader.loadClass()
またはClassLoader.findSystemClass()
メソッドを使用して実行時にクラスをロードしようとすると、発生する可能性がありますnotクラスパスで必要なクラスを見つけます。class path
_を確認し、クラスがない場合はクラスパスに追加する必要があります。2)NoClassDefFoundError
これは、クラスが_compile time
_中に存在し、何らかの理由で_run time
_中に使用できない場合に発生します。これは、ロードされているクラスがpresent
内のclasspath
であることを意味しますが、このクラスに必要な依存classe(s)
の1つは、次のいずれかです削除 =または失敗コンパイラーによってロードされます。
この場合、_classes which are dependent on this class
_のみをチェックする必要があります。
ClassNotFoundExceptionとNoClassDefFoundErrorのすべて 記事では、ClassNotFoundExceptionとNoClassDefFoundErrorの違いを例を挙げて説明しています。
Class.forName()またはClassLoader.findSystemClass()またはClassLoader.loadClass()メソッドを使用して文字列名でクラスをロードするようにJVMに指示し、クラスパスに上記のクラスが見つからない場合に発生するチェック例外です。
ほとんどの場合、この例外は、必要なJARファイルでクラスパスを更新せずにアプリケーションを実行しようとしたときに発生します。たとえば、JDBCコードを実行してデータベース、つまりMySQLに接続しているときにこの例外が発生した可能性がありますが、クラスパスにjarがありません。
public class Test {
public static void main(String[] args) throws Exception {
// Provide any class name to Class.forName() which does not exist
// Or compile Test.Java and then manually delete Person.class file so Person class will become unavailable
// Run the program using Java Test
Class clazz = Class.forName("Person");
Person person = (Person) clazz.newInstance();
person.saySomething();
}
}
class Person {
void saySomething() {
System.out.println("Hello");
}
}
Java.lang.Errorのサブタイプであり、Errorクラスは、アプリケーションで実際に発生してはならない異常な動作を示しますが、アプリケーション開発者はそれをキャッチしようとすべきではありません。これは、JVMでのみ使用されます。
NoClassDefFoundErrorは、JVMがコード実行の一部である特定のクラス(通常のメソッド呼び出しの一部として、またはnewキーワードを使用してインスタンスを作成する一部として)をロードしようとしたときに発生し、そのクラスはクラスパスに存在しないが存在していたプログラムを実行するにはコンパイルする必要があるため、コンパイル時。存在しないクラスを使用しようとすると、コンパイラはコンパイルエラーを発生させます。
public class Test {
public static void main(String[] args) throws Exception {
// Do javac on Test.Java,
// Program will compile successfully because Empoyee class exits
// Manually delete Employee.class file
// Run the program using Java Test
Employee emp = new Employee();
emp.saySomething();
}
}
class Employee {
void saySomething() {
System.out.println("Hello");
}
}
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ランタイムシステムは以下のように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)
NoClassDefFoundErrorが発生するケースの1つは、クラスJVMがアクセスを試みているときにクラスパスに見つからない場合です。ただし、クラスパスにクラスが存在する場合、ClassNotFoundExceptionが発生します。
つまり、コンパイル時にクラスが存在したが、実行時にJavaクラスパスで利用できない)場合、NoClassDefFoundErrorが発生します。
クラスパスにクラスBが含まれていない場合は、明示的な-classpathオプションで実行してみてください。