NoClassDefFoundError和ClassNotFoundException之间有什么原因和区别?

和 有什么区别?NoClassDefFoundErrorClassNotFoundException

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

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

我遇到的可能原因:

  1. 代码客户端未包含的包build.xml
  2. 我们正在使用的新 jar 缺少运行时类路径
  3. 版本与以前的 jar 冲突

当我今天遇到这些时,我会采取一种跟踪和错误的方法让事情运转起来。我需要更多的清晰度和理解。


答案 1

与 Java API 规范的区别如下。

对于 ClassNotFoundException

当应用程序尝试使用以下命令通过其字符串名称加载类时抛出:

  • 类 中的方法。forNameClass
  • 类 中的方法。findSystemClassClassLoader
  • 类 中的方法。loadClassClassLoader

但是找不到具有指定名称的类的定义。

对于 NoClassDefFoundError

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

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

因此,似乎在成功编译源代码时会发生这种情况,但在运行时,找不到所需的文件。这可能是在 JAR 文件的分发或生产中可能发生的事情,其中并未包含所有必需的文件。NoClassDefFoundErrorclassclass

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

两者之间的区别在于,一个是 一个是 ., 另一个是 .with 是 一个,它源于 Java 虚拟机在查找它期望找到的类时遇到问题。本应在编译时工作的程序无法运行,因为找不到文件,或者与编译时生成或遇到的程序不同。这是一个非常严重的错误,因为程序不能由JVM启动。ErrorExceptionNoClassDefFoundErrorErrorclass

另一方面,是 一个 ,所以它在某种程度上是预期的,并且是可恢复的。使用反射可能容易出错(因为有一些期望,事情可能不会按预期进行。没有编译时检查来查看所有必需的类是否存在,因此查找所需类的任何问题都将在运行时出现。ClassNotFoundExceptionException


答案 2

当 ClassLoader 找不到报告的类时,将引发 ClassNotFoundException。这通常意味着 CLASSPATH 中缺少该类。这也可能意味着有问题的类正在尝试从父类装入器中装入的另一个类装入,因此子类装入器中的类不可见。在更复杂的环境中(如应用程序服务器)中工作时,有时会出现这种情况(WebSphere因此类类装入器问题而臭名昭着)。

人们经常倾向于混淆,但有一个重要的区别。例如,一个异常(一个错误实际上是自是java.lang.Error的子类),比如java.lang.NoClassDefFoundErrorjava.lang.ClassNotFoundExceptionjava.lang.NoClassDefFoundError

java.lang.NoClassDefFoundError:
org/apache/activemq/ActiveMQConnectionFactory

并不意味着 ActiveMQConnectionFactory 类不在 CLASSPATH 中。事实上恰恰相反。这意味着类ActiveMQConnectionFactory是由ClassLoader找到的,但是当尝试加载该类时,它在读取类定义时遇到了错误。当有问题的类具有静态块或成员使用 ClassLoader 找不到的类时,通常会发生这种情况。因此,要找到罪魁祸首,请查看相关类的源代码(在本例中为ActiveMQConnectionFactory),并使用静态块或静态成员查找代码。如果您无权访问源代码,则只需使用 JAD 对其进行反编译即可。

在检查代码时,假设您找到一行如下所示的代码,请确保 CLASSPATH 中的类 SomeClass。

private static SomeClass foo = new SomeClass();

提示:要找出一个类属于哪个jar,您可以使用网站jarFinder。这允许您使用通配符指定类名,并在其 jar 数据库中搜索该类。jarhoo允许你做同样的事情,但它不再免费使用。

如果要在本地路径中找到类所属的 jar,可以使用类似 jarscan ( http://www.inetfeedback.com/jarscan/ ) 之类的实用程序。您只需指定要查找的类以及您希望它开始在 jar 和 zip 文件中搜索该类的根目录路径。


推荐