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

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

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

我发现的可能原因是:

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

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


当前回答

当我需要复习的时候,我会一遍又一遍地提醒自己

ClassNotFoundException

类层次结构

ClassNotFoundException extends ReflectiveOperationException extends Exception extends Throwable

在调试

Required jar,类路径中缺少类。 验证所有必需的jar都在jvm的类路径中。

NoClassDefFoundError

类层次结构

NoClassDefFoundError extends LinkageError  extends Error extends Throwable

在调试

Problem with loading a class dynamically, which was compiled properly Problem with static blocks, constructors, init() methods of dependent class and the actual error is wrapped by multiple layers [especially when you use spring, hibernate the actual exception is wrapped and you will get NoClassDefError] When you face "ClassNotFoundException" under a static block of dependent class Problem with versions of class. This happens when you have two versions v1, v2 of same class under different jar/packages, which was compiled successfully using v1 and v2 is loaded at the runtime which doesn't has the relevant methods/vars& you will see this exception. [I once resolved this issue by removing the duplicate of log4j related class under multiple jars that appeared in the classpath]

其他回答

ClassNotFoundException是一个检查异常,当我们告诉JVM使用class . forname()或ClassLoader.findSystemClass()或ClassLoader.loadClass()方法根据类的字符串名加载类,并且在类路径中没有找到所提到的类时,就会发生这种异常。

大多数情况下,当您试图运行应用程序而不使用所需的JAR文件更新类路径时,会发生此异常。例如,你可能已经看到这个异常时,做JDBC代码连接到你的数据库,即mysql,但你的类路径没有JAR。

NoClassDefFoundError发生错误当JVM试图加载一个特定的类的代码执行(作为一个正常的一部分方法调用或使用新的关键字创建一个实例的一部分),这类在类路径中不存在,但在编译时,因为为了执行程序需要编译它,如果你正在使用一个类不存在编译器会提高编译错误。

下面是简短的描述

你可以阅读关于ClassNotFoundException Vs NoClassDefFoundError的一切来了解更多细节。

例# 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。

两者都是运行时异常。

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

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

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

从http://www.javaroots.com/2013/02/classnotfoundexception-vs.html:

ClassNotFoundException:类装入器在类路径中找不到所需的类时发生。因此,基本上您应该检查类路径并在类路径中添加类。

NoClassDefFoundError:这更难调试和查找原因。当在编译时存在所需的类,但在运行时类被更改或删除,或者类的静态初始化抛出的异常时,将引发此异常。这意味着要加载的类存在于类路径中,但该类所需的类之一要么被删除,要么被编译器加载失败。你应该看到依赖于这个类的类。

例子:

public class Test1
{
}


public class Test 
{
   public static void main(String[] args)
   {
        Test1 = new Test1();    
   }

}

现在,在编译完这两个类之后,如果删除Test1.class文件并运行Test类,它将抛出

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和NoClassDefFoundError的区别