两者有什么区别 NoClassDefFoundError
以及 ClassNotFoundException
?
是什么导致他们被扔出去的?如何解决?
在修改现有代码以包含新的jar文件时,我经常会遇到这些问题。对于通过webstart分发的java应用程序,我在客户端和服务器端都找到了它们。
我遇到的可能原因:
不包括在 build.xml
对于代码的客户端
我们正在使用的新jar缺少运行时类路径
版本与以前的jar冲突
当我今天遇到这些问题时,我会采取循序渐进的方法来解决问题。我需要更多的清晰和理解。
8条答案
按热度按时间bxgwgixi1#
与javaapi规范的区别如下。
为了
ClassNotFoundException
:当应用程序试图通过其字符串名称加载类时引发,使用:
这个
forName
类中的方法Class
.这个
findSystemClass
类中的方法ClassLoader
.这个
loadClass
类中的方法ClassLoader
.但找不到具有指定名称的类的定义。
为了
NoClassDefFoundError
:如果java虚拟机或
ClassLoader
示例尝试加载类的定义(作为普通方法调用的一部分或使用新表达式创建新示例的一部分),但找不到该类的定义。编译当前执行的类时,已存在搜索的类定义,但无法再找到该定义。
所以,看起来
NoClassDefFoundError
在成功编译源代码时发生,但在运行时class
找不到文件。这可能是在jar文件的分发或生产过程中发生的事情,在这种情况下并不需要所有class
包括文件。至于
ClassNotFoundException
,它可能源于试图在运行时对类进行反射调用,但程序试图调用的类不存在。两者的区别在于一个是
Error
另一个是一个Exception
. 与NoClassDefFoundError
是一个Error
它产生于java虚拟机在寻找它期望找到的类时遇到问题。在编译时工作的程序无法运行,因为class
找不到文件,或者与编译时生成或遇到的文件不同。这是一个非常严重的错误,因为程序不能由jvm启动。另一方面
ClassNotFoundException
是一个Exception
因此,这在某种程度上是意料之中的,而且是可以恢复的。使用反射很容易出错(因为有些人认为事情可能不会按预期进行)。没有编译时检查来查看所有必需的类是否存在,因此查找所需类的任何问题都将在运行时出现。igsr9ssn2#
当类加载器找不到报告的类时,将引发classnotfoundexception。这通常意味着类路径中缺少类。这也可能意味着所讨论的类正试图从另一个加载在父类加载器中的类中加载,因此子类加载器中的类不可见。在更复杂的环境(比如应用服务器)中工作时有时会出现这种情况(websphere因此类类加载器问题而臭名昭著)。
人们往往容易混淆
java.lang.NoClassDefFoundError
与java.lang.ClassNotFoundException
但是有一个重要的区别。例如一个异常(一个真正的错误)java.lang.NoClassDefFoundError
是java.lang.error的子类并不意味着activemqconnectionfactory类不在类路径中。事实恰恰相反。这意味着类加载器找到了类activemqconnectionfactory,但是在尝试加载该类时,它在读取类定义时遇到了错误。当所讨论的类具有静态块或成员,而这些静态块或成员使用的是类加载器找不到的类时,通常会发生这种情况。因此,要找到罪魁祸首,请查看相关类的源代码(本例中为activemqconnectionfactory),并使用静态块或静态成员查找代码。如果您没有访问源代码的权限,那么只需使用jad对其进行反编译。
在检查代码时,假设您发现一行如下所示的代码,请确保类someclass位于类路径中。
提示:要找出类属于哪个jar,可以使用网站jarfinder。这允许您使用通配符指定类名,并在jar数据库中搜索该类。jarhoo允许你做同样的事情,但它不再免费使用。
如果您想在本地路径中找到一个类所属的jar,可以使用jarscan(http://www.inetfeedback.com/jarscan/ ). 您只需指定要定位的类和根目录路径,以便在jars和zip文件中开始搜索该类。
yks3o0rb3#
NoClassDefFoundError
基本上是一个联动误差。它发生在您尝试示例化一个对象时(静态使用“new”),而在编译期间找不到它。ClassNotFoundException
更一般,并且在尝试使用不存在的类时是运行时异常。例如,在函数中有一个参数接受一个接口,有人传入实现该接口的类,但您无权访问该类。它还包括动态类加载的情况,例如loadClass()
或者Class.forName()
.edqdpe6u4#
当代码运行“new y()”并且找不到y类时,会发生noclassdeffounderror(ncdfe)。
可能只是像其他注解所建议的那样,y从类装入器中丢失了,但可能是y类没有签名或签名无效,或者y是由代码看不到的其他类装入器装入的,甚至y依赖于z,而z由于上述任何原因都无法装入。
如果发生这种情况,jvm将记住加载x(ncdfe)的结果,并且每次您请求y时它都会抛出一个新的ncdfe,而不会告诉您原因:
将此另存为a.java
代码只是尝试示例化一个新的“b”类两次,除此之外,它没有任何bug,也没有做任何事情。
使用编译代码
javac a.java
,然后通过调用java -cp . a
--它应该只打印出两行文本,并且应该运行良好,没有错误。然后删除“a$b.class”文件(或者用垃圾填充它,或者在上面复制一个.class)来模拟丢失或损坏的类。下面是发生的情况:
第一次调用会导致classnotfoundexception(当类加载器找不到类时抛出),必须将其 Package 在未检查的noclassdeffounderror中,因为有问题的代码(
new b()
)应该就行了。第二次尝试当然也会失败,但是正如您所看到的, Package 的异常不再存在,因为类装入器似乎记住了失败的类装入器。你只看到ncdfe完全不知道到底发生了什么。
因此,如果您曾经看到一个没有根本原因的ncdfe,那么您需要查看是否可以追溯到第一次加载类时,以找到错误的原因。
olqngx595#
从http://www.javaroots.com/2013/02/classnotfoundexception-vs.html:
ClassNotFoundException
:当类加载器在类路径中找不到所需的类时发生。所以,基本上你应该检查你的类路径并在类路径中添加类。NoClassDefFoundError
:这更难调试并找到原因。当在编译时存在所需的类,但在运行时更改或删除这些类,或者类的静态初始化引发异常时,就会引发这种情况。这意味着要加载的类存在于类路径中,但该类所需的某个类被编译器删除或加载失败。所以你应该看到依赖于这个类的类。例子:
现在编译完这两个类之后,如果删除test1.class文件并运行test class,它将抛出
gj3fmq9x6#
是什么原因让他们每一个和任何思想过程如何处理这些错误?
他们关系密切。一
ClassNotFoundException
当java按名称查找特定类而无法成功加载该类时引发。一NoClassDefFoundError
当java查找链接到某个现有代码中的类时抛出,但由于某种原因(例如,错误的类路径、错误的java版本、错误的库版本)而找不到该类,这是完全致命的,因为它表明某些东西出了严重错误。如果你有c的背景,cnfe就像是失败的
dlopen()
/dlsym()
而ncdfe是链接器的问题;在第二种情况下,相关的类文件不应该在您试图使用它们的配置中实际编译。xxb16uws7#
示例#1:
如果
com/example/Class1
在任何类路径中都不存在,然后它抛出ClassNotFoundException
.示例2:
如果
com/example/Class2
在编译b时存在,但在执行时找不到,然后抛出NoClassDefFoundError
.两者都是运行时异常。
mrphzbgm8#
当试图通过字符串引用类来加载该类时,将引发classnotfoundexception。例如,class.forname()中的参数是一个字符串,这可能导致传递给类加载器的二进制名称无效。
当遇到可能无效的二进制名称时抛出classnotfoundexception;例如,如果类名具有“/”字符,则您将得到classnotfoundexception。当直接引用的类在类路径上不可用时,也会抛出它。
另一方面,抛出noclassdeffounderror
当类的实际物理表示形式.class文件不可用时,
或者班上的蜜蜂