NoClassDefFoundError和ClassNotFoundException之间的区别是什么?

是什么导致它们被抛出?如何解决这些问题?

在修改现有代码以包含新的jar文件时,我经常遇到这些可抛出的文件。 我已经在客户端和服务器端为一个通过webstart分发的java应用程序击中了它们。

我发现的可能原因是:

未包含在代码客户端build.xml中的包 我们正在使用的新jar缺少运行时类路径 版本与上一个jar冲突

当我今天遇到这些问题时,我采取了一种反复尝试的方法来让事情正常运行。我需要更多的清晰和理解。


当前回答

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

编译上述程序时,将生成两个.class文件。一个是a类,另一个是b类。如果你删除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)

其他回答

获得这些错误的原因是什么,以及如何处理这些错误的思想过程?

它们是密切相关的。当Java按名称查找特定类且无法成功加载时,将抛出ClassNotFoundException。NoClassDefFoundError会在Java寻找链接到现有代码的类时抛出,但由于这样或那样的原因(例如,错误的类路径、错误的Java版本、错误的库版本)无法找到它,这是完全致命的,因为它表明某些事情发生了严重错误。

如果你有一个C背景,一个CNFE就像一个失败的dlopen()/dlsym()和一个NCDFE是一个链接器的问题;在第二种情况下,相关的类文件不应该在您试图使用它们的配置中实际编译过。

在实践中添加一个可能的原因:

ClassNotFoundException:正如cletus所说,当接口的继承类不在类路径中时使用接口。例如,服务提供者模式(或服务定位器)试图定位一些不存在的类 NoClassDefFoundError:找到了给定的类,但没有找到给定类的依赖项

在实践中,Error可能会被无声地抛出,例如,你提交了一个计时器任务,在计时器任务中它抛出了Error,而在大多数情况下,你的程序只捕获Exception。然后Timer主循环结束,没有任何信息。与NoClassDefFoundError类似的错误是ExceptionInInitializerError,当您的静态初始化器或静态变量的初始化器抛出异常时。

当试图通过String引用该类来加载该类时,将抛出ClassNotFoundException。例如,Class.forName()中的参数to是一个字符串,这可能会将无效的二进制名称传递给类加载器。

当遇到可能无效的二进制名称时抛出ClassNotFoundException;例如,如果类名有'/'字符,你一定会得到一个ClassNotFoundException。当直接引用的类在类路径上不可用时,它也会被抛出。

另一方面,NoClassDefFoundError被抛出

when the actual physical representation of the class - the .class file is unavailable, or the class been loaded already in a different classloader (usually a parent classloader would have loaded the class and hence the class cannot be loaded again), or if an incompatible class definition has been found - the name in the class file does not match the requested name, or (most importantly) if a dependent class cannot be located and loaded. In this case, the directly referenced class might have been located and loaded, but the dependent class is not available or cannot be loaded. This is a scenario where the directly referenced class can be loaded via a Class.forName or equivalent methods. This indicates a failure in linkage.

简而言之,当类加载器无法找到或加载类定义时,通常会在new()语句或加载先前不存在的类的方法调用上抛出NoClassDefFoundError(与ClassNotFoundException基于字符串的类加载相反)。

最终,当ClassLoader无法加载类时,由ClassLoader实现抛出ClassNotFoundException实例。大多数自定义类加载器实现执行此操作,因为它们扩展了URLClassLoader。通常类加载器不会在任何方法实现上显式抛出NoClassDefFoundError——这个异常通常是由HotSpot编译器中的JVM抛出的,而不是由类加载器本身抛出的。

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

编译上述程序时,将生成两个.class文件。一个是a类,另一个是b类。如果你删除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)

给定类装入器sussystem动作:

这是一篇帮助我理解差异的文章:http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-5.html

If an error occurs during class loading, then an instance of a subclass of LinkageError must be thrown at a point in the program that (directly or indirectly) uses the class or interface being loaded. If the Java Virtual Machine ever attempts to load a class C during verification (§5.4.1) or resolution (§5.4.3) (but not initialization (§5.5)), and the class loader that is used to initiate loading of C throws an instance of ClassNotFoundException, then the Java Virtual Machine must throw an instance of NoClassDefFoundError whose cause is the instance of ClassNotFoundException.

所以ClassNotFoundException是NoClassDefFoundError的根本原因。 NoClassDefFoundError是类型加载错误的一种特殊情况,发生在链接步骤。