ClassNotFoundException vs NoClassDefFoundError

我已经浏览了这个线程 NoClassDefFoundError和ClassNotFoundException之间的原因和区别是什么?这就是线程中具有最大ups的ans之一:NoClassDefFoundError:“所以,似乎NoClassDefFoundError在源代码成功编译时发生,但在运行时,找不到所需的类文件。这可能是在JAR文件的分发或生产中可能发生的事情,其中不包括所有必需的类文件。

ClassNotFoundException :至于ClassNotFoundException,它似乎源于试图在运行时对类进行反射调用,但程序尝试调用的类并不存在。

我做了一个小实验。我创建了一个主类,A类,并尝试调用其他类,从中调用B类,编译成功。

然后我删除了在A类中调用的B类。我得到了java.lang.ClassNotFoundException,但根据tread中的答案,我应该得到NoClassDefFoundError(源代码已成功编译,但在运行时找不到类文件)任何人都可以解释我在线程中对ans的解释中缺少什么?

package com.random;

public class A {

    public static void main(String[] args) {
        B b= new B();

    }

}

 package com.random;

public class B {



}

答案 1

NoClassDefFoundError

如果 Java 虚拟机或 ClassLoader 实例尝试在类的定义中加载(作为常规方法调用的一部分或使用新表达式创建新实例的一部分),并且找不到该类的定义,则抛出。

编译当前正在执行的类时,搜索的类定义存在,但无法再找到该定义。


ClassNotFoundException

当应用程序尝试通过其字符串名称加载类时,使用:类 Class 中的 forName 方法引发。类 ClassLoader 中的 findSystemClass 方法。类类装入器中的 loadClass 方法。


您必须了解无法实现您删除的定义无法找到,因为无法找到本身,这会自动抛出.JVMclassclassClassNotFoundException

此异常发生在这样,因此无论它是否首先编译都无关紧要,您删除了该文件,因此无法找到它并抛出.runtimeexception

请注意,这实际上不是一个例外,它是一个派生自,而直接派生自 。NoClassDefFoundErrorErrorLinkageErrorClassNotFoundExceptionjava.lang.Exception

要恢复,全局简单地表示尝试访问根据代码应该存在但实际上不存在(或不在类路径中)的东西。NoClassDefFoundErrorJVMruntimecompiled


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

现在创建一个执行该方法的 n 个可执行文件。您可以在.jarmainManifest.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

答案 2

井。。。 当运行时尝试查找由某些示例方法命名的类时,将发生,方法采用字符串参数并尝试查找具有此名称的类。在这种情况下,类名是刺痛的,只能在运行时检查。这里的例外清楚地说...找不到此“类”。所以。。。它可能由于两个原因而发生:ClassNotFoundExceptionStringClass.forName(java.lang.String)

原因 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

这里的运行时知道该类是有效的,因为它编译成功...但它找不到“类定义”。