web-dev-qa-db-ja.com

ClassNotFoundExceptionとNoClassDefFoundError

私はこのスレッドを通過しました 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 {



}
22
Deen John

NoClassDefFoundError

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

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


ClassNotFoundException

アプリケーションが文字列名を使用してクラスにロードしようとすると、クラスClassのforNameメソッドを使用してスローされます。クラスClassLoaderのfindSystemClassメソッド。クラスClassLoaderのloadClassメソッド。


JVMclass自体を自動的に見つけることができないため、削除したclassの定義を見つけることができないことを理解する必要があります。 ClassNotFoundExceptionをスローします。

この例外はruntimeで発生するため、最初にコンパイルしたかどうかに関係なく、ファイルを削除したため、ファイルが見つからず、exceptionをスローしません。

NoClassDefFoundErrorは実際には例外ではなく、Errorから派生したLinkageErrorであり、ClassNotFoundExceptionJava.lang.Exceptionから直接派生することに注意してください。

再開するには、NoClassDefFoundErrorはグローバルにJVMruntimecompiledコードに従って存在するはずの何かにアクセスしようとしたが、実際には存在しないことを単に意味します存在する(またはクラスパスにない)。


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
13

ええと... 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を取得します。

ここで、ランタイムは、正常にコンパイルされたため、クラスが有効であることを認識していますが、「クラス定義」を見つけることができません。

10

違いは、誰がクラスのロードを要求したかによります

  • ClassNotFoundExceptionは、コードがクラスを直接ロードしようとするとスローされます、クラスの完全修飾名を表すString引数を渡します。
    • 例えばClass.forName(String)、またはClassLoader.loadClass(String)
  • NoClassDefFoundErrorは、JVMがクラスを間接的にロードするよう要求された場合にスローされます
    • 例えばクラスAがクラスBを使用していて、クラスBがクラスパス上にない場合、NoClassDefFoundErrorがスローされます。
7

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ファイルを実行すると、そのエラーが表示されます!

2
Jeremy

以前の回答で述べたように、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
IamVickyAV

1)ClassNotFoundException

  1. これは、Class.forName()またはClassLoader.loadClass()またはClassLoader.findSystemClass()メソッドを使用して実行時にクラスをロードしようとすると、発生する可能性がありますnotクラスパスで必要なクラスを見つけます。
  2. この場合、_class path_を確認し、クラスがない場合はクラスパスに追加する必要があります。
  3. これはJava.lang.Exceptionクラスから派生したchecked Exceptionです。
  4. これはexplicit loadingの下にあります。

2)NoClassDefFoundError

  1. これは、クラスが_compile time_中に存在し、何らかの理由で_run time_中に使用できない場合に発生します。これは、ロードされているクラスがpresent内のclasspathであることを意味しますが、このクラスに必要な依存classe(s)の1つは、次のいずれかです削除 =または失敗コンパイラーによってロードされます。

  2. この場合、_classes which are dependent on this class_のみをチェックする必要があります。

  3. Java.lang.LinkageErrorから派生したErrorです。
  4. これはimplicitローディングの下にあります。
1
Rohit Gaikwad

ClassNotFoundExceptionとNoClassDefFoundErrorのすべて 記事では、ClassNotFoundExceptionとNoClassDefFoundErrorの違いを例を挙げて説明しています。

ClassNotFoundException Vs NoClassDefFoundError -- Programming Mitra

ClassNotFoundException

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");
    }
}

NoClassDefFoundError

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");
    }
}
0
Naresh Joshi

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)
0
Neeraj Gahlawat

NoClassDefFoundErrorが発生するケースの1つは、クラスJVMがアクセスを試みているときにクラスパスに見つからない場合です。ただし、クラスパスにクラスが存在する場合、ClassNotFoundExceptionが発生します。

つまり、コンパイル時にクラスが存在したが、実行時にJavaクラスパスで利用できない)場合、NoClassDefFoundErrorが発生します。

クラスパスにクラスBが含まれていない場合は、明示的な-classpathオプションで実行してみてください。

0
Ajit Lakhwani