原因是什么和是什么之间的差异NoClassDefFoundError和ClassNotFoundException?
-
12-09-2019 - |
题
之间的区别是什么 NoClassDefFoundError
和 ClassNotFoundException
?
是什么原因导致他们被扔?他们怎么能解决?
我经常遇到这些throwable异常时修改现有的编码,包括新的罐子文件。我已打了他们在客户面和服务器方java应用程序通过分布式webstart。
可能的原因,我遇到:
- 包不包括
build.xml
对客户的侧的代码 - runtime类路径失踪的新的罐子,我们使用
- 版本的冲突与以前的罐子
当我收到这些我今天采取一个跟踪和错误的做法得到事工作。我需要更清晰和谅解。
解决方案
差从API规格如下。
扔当应用程序尝试 加载一级通过其串 名称的使用:
- 的
forName
方法中的类Class
.- 的
findSystemClass
方法中的类ClassLoader
.- 的
loadClass
方法中的类ClassLoader
.但没有定义类 指定名称可能被发现。
扔如果Java虚拟机或 一个
ClassLoader
实例,试图负荷 定义中的一类(为部分 一个正常的方法调用的一部分或作为 创建一个新的实例,使用新的 表达的),并没有定义的 类可以找到。搜索到的-为类定义 存在当前执行 类编制的,但该定义 不能再被发现。
因此,它的出现, NoClassDefFoundError
发生时的来源是成功地编制,但是在运行时,所需要的 class
文件没有找到。这可能是一些可能发生在分发或生产的瓶子文件,那里不是所有的需要 class
文件都包括在内。
作为对 ClassNotFoundException
, 看,似乎它可能来自试图使反射呼吁课程在运行时,但这类程序是试图呼叫不存在。
两者之间的区别是,一个是 Error
和其他的是一个 Exception
.与 NoClassDefFoundError
是一个 Error
和它产生于Java虚拟机有问题找到一个类预期找到。一个程序,预计工作在编写时不可以运行,因为 class
文件没有被找到,或者是不相同的作物生产或遇到在编译时间。这是一个非常严重的错误,因为该程序不能发起的JVM。
另一方面, ClassNotFoundException
是一个 Exception
, ,因此它是有些预期,并且是什么,是恢复。使用反射是可以容易出错(如有的是一些期望,事情可能不会如预期的那样。没有编写时检查所有所需课程的存在,所以,任何问题寻找所需要的课程将出现在运行时间。
其他提示
一ClassNotFoundException时引发的报告类未找到通过这类装入器。这通常意味着这类缺失类路径。这还可能意味着这类问题是试图将载入另一类的其装载在父类装入器,因此该类从儿童的类装载器是不可见的。这是有时的情况下,当工作更加复杂环境中的应用程序服务器(WebSphere是臭名昭着的这类装入器问题)。
人们往往往往会混淆 java.lang.NoClassDefFoundError
与 java.lang.ClassNotFoundException
但是有一个重要的区别。例如一个例外(一个错误因为真的 java.lang.NoClassDefFoundError
是一个子类。郎。错误)像
java.lang.NoClassDefFoundError:
org/apache/activemq/ActiveMQConnectionFactory
并不意味着ActiveMQConnectionFactory类是不在该类路径。事实上,它完全相反。它意味着这类ActiveMQConnectionFactory被发现的类装入器然而,当试图载的类,它遇到了一个错误的读类定义。这通常发生在流问题具有静态块或成员使用哪一类的未找到通过这类装入器。因此寻找罪魁祸首,视的来源之类的问题(ActiveMQConnectionFactory在这种情况下),并寻找代码使用静态块或静态的成员。如果你没有访问的来源,那么只需进行它的使用JAD.
在审查的码,说你找到一个线的代码如下,确保这类SomeClass在类路径。
private static SomeClass foo = new SomeClass();
提示:要找出这瓶子一类属于,可以使用的网站jarFinder.这可以让你指定一个类名称中使用通配符的和搜索类在其数据库中的罐子。jarhoo让你做同样的事情,但它不再是免费的使用。
如果你想查找这瓶子一类属于在当地的路径,可以使用的实用程序,如jarscan( http://www.inetfeedback.com/jarscan/ ).你只是类指定你想来定位和根目录的路径在那里你会喜欢这开始寻找的类罐和压缩文件。
NoClassDefFoundError
是一个错误的联系基本上是这样。这发生时当你尝试和初始化物(静态"新的")并不时发现它是在汇编。
ClassNotFoundException
更一般而是一个运行异常,当你试图用一种类,并不存在。例如,有一个参数的一个函数接受一个接口,有人传递一个类实现该接口但你没有接到类。它还涵盖的情况下动态级载荷,例如使用 loadClass()
或 Class.forName()
.
一NoClassDefFoundError(NCDFE)发生时当你的代码运行"新Y()",它不能找到Y类。
这可能只是Y缺失类装载喜欢的其他意见建议,但它可能是Y类没有签署或具有无效的签名,或者说,Y载通过不同类加载不可见你的码,或甚至Y取决于Z其无法被载入对于上述任何原因。
如果发生这种情况,然后JVM会记得的结果载X(NCDFE),它将只是扔一个新的NCDFE每次你要求Y没有告诉你为什么:
class a { static class b {} public static void main(String args[]) { System.out.println("First attempt new b():"); try {new b(); } catch(Throwable t) {t.printStackTrace();} System.out.println("\nSecond attempt new b():"); try {new b(); } catch(Throwable t) {t.printStackTrace();} } }
保存如此a.java 某个地方
代码只是试图化的一个新的"b"类的两倍,其他比的是,它没有任何错误,它不会做任何事情。
汇编码 javac a.java
, 然后运行的一个通过调用 java -cp . a
-这应该只是打印出来的两行文字,并且它应该没有错误。
然后删除"a$b.class"文件(或填写垃圾,或者复制a.class 在这)模拟缺失或损坏的类。这里发生了什么:
First attempt new b(): java.lang.NoClassDefFoundError: a$b at a.main(a.java:5) Caused by: java.lang.ClassNotFoundException: a$b at java.net.URLClassLoader$1.run(URLClassLoader.java:200) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:188) at java.lang.ClassLoader.loadClass(ClassLoader.java:307) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301) at java.lang.ClassLoader.loadClass(ClassLoader.java:252) at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320) ... 1 more Second attempt new b(): java.lang.NoClassDefFoundError: a$b at a.main(a.java:7)
第一调用结果在ClassNotFoundException(引发的类装载时,它无法找到类),其中必须包裹在一个未经检查的NoClassDefFoundError,由于编码问题(new b()
)应当只是工作。
第二次尝试,当然会失败了,但是你可以看到包裹的例外是没有更多,因为这类装入器似乎记得失败类装载机。你只看到NCDFE绝对没有任何的线索到底发生了什么。
所以如果你曾经看见一个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 文件和运行测试类,它将引发
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
是扔当Java去寻找某一特定类别的名称并不能成功地载入它。一个 NoClassDefFoundError
是扔当Java去寻找一个类联系到一些现有的编码,但找不到它的一个原因或另一个(例如,错误的类路径,是错误的版本的Java,是错误的版本图书馆),并充分致命,因为它表示了严重错误的。
如果你已经有了一个C背景下,CNFE是喜欢一个失败 dlopen()
/dlsym()
和一个NCDFE是一个问题,与接头;在第二种情况下,该类文件关注不应该已经实际上汇编在结构你试图使用它们。
例#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();
}
}
如果 com/example/Class2
存在的话,汇编B,但没有找到同时执行,然后它引发 NoClassDefFoundError
.
这两个运行时间的例外情况。
ClassNotFoundException 是扔在那里是试图负荷类通过引用它通过一串。例如参数。forName()is a String,并且这就提出了潜在的无效二名被通过这类装入器。
该ClassNotFoundException时引发可能无效的二名遇到的;例如,如果这类名称的'/'角色,你一定要得到一个ClassNotFoundException.它也是引发当直接引用类不适用于该类路径。
另一方面, NoClassDefFoundError 是扔
- 当实际的物理表示类。类文件,不可用,
- 或类装已经在不同类装入器(通常是父类装入器将装载的类以及因此类不能再次装载),
- 或者如果不兼容的类的定义已经发现的-的名称在该类文件不匹配所请求的名称,
- 或者(最重要的是)如果一个从属类不能定位和加载。在这种情况下,直接引用类可能已经位于并装载,但所依赖的类是不可或不可能装载。这是一个方案,其中直接引用类可以通过加载一类。forName或者等效方法。这表示的失败是相互关联的。
在短短的,一个NoClassDefFoundError是通常引发在新的()发言或方法调用的,载入先前不存在类(而不是基于字符串载的类ClassNotFoundException),当这类装载器是无法找到或负荷类定义(s)。
最终,它是最多的类装入器实行抛出的实例ClassNotFoundException时无法载入一类。大多数定义类装入器的实现方式执行此,因为他们延长URLClassLoader.通常类装入器没有明确扔NoClassDefFoundError上的任何方法实施这种例外是通常引发从JVM在的热点编译器,而不是通过类装入器本身。
与名称本身,我们可以很容易地确定一个从
Exception
和另一种是从Error
.
例外: 例外情况发生在执行的程序。程序员可以处理这些例外通过尝试抓住块。我们有两种类型的例外情况。检查异常引发在编译时间。运行时的例外情况是在运行时,这些例外通常会发生,因为不良的程序。
错误: 这些不是例外情况,它的范围之内的程序员。这些错误通常都被丢弃的JVM。
差异:
ClassNotFoundException:
- 舱装载机失败 验证 一类字节的代码,我们提 链接相 的 类子系统加载 我们得到
ClassNotFoundException
. ClassNotFoundException
是一种检查的例外来直接从java.lang.Exception
类和需要提供明确的处理它ClassNotFoundException
当有一个 明确载 类是涉及通过提供名称的类在运行时使用的类装载器。loadClass(),类。forName()以及类装入器。findSystemClass().
NoClassDefFoundError:
- 舱装载机失败 解决 引用一个类 链接相 的 类子系统加载 我们得到
NoClassDefFoundError
. NoClassDefFoundError
是一个错误来自LinkageError
级,这是用来表示的错误情况,其中一类依赖于一些其他类别和类具有不兼容的改后的汇编。NoClassDefFoundError
是的结果 隐装 类,因为一方法调,从这类或任何变的访问。
相似之处:
- 既
NoClassDefFoundError
和ClassNotFoundException
是有关于不可用的一类在运行时间。 - 既
ClassNotFoundException
和NoClassDefFoundError
有关Java类路径。
鉴于这类装载sussystem行动:
这是一篇文章,帮了我很多了解的差异: http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-5.html
如果差错发生在课堂的装载、随后的一个实例 类的 LinkageError 必须抛在一点的程序 (直接或间接地)使用类或接口正在加载。
如果Java虚拟机曾经尝试负载一个C类的期间 核查(§5.4.1)或决议(第5.4.3)(但不是初始化 (§5.5)),该类的装载机就是用来启动的装载C 抛出的实例 ClassNotFoundException, 然后Java虚拟 机器必须扔一个实例 NoClassDefFoundError 其原因是 实例 ClassNotFoundException.
所以 ClassNotFoundException 是一个根本原因的 NoClassDefFoundError.
和一个 NoClassDefFoundError 是一种特殊情况的类型装载的错误,即发生在 链接 步骤。
添加的一个原因可能在实践:
- ClassNotFoundException:作为克莱说,你使用的接口,同时继承的类的接口是不在该类路径。例如,服务提供模式(或 服务定位器)试图找到一些不存在的类
- NoClassDefFoundError:给类被发现时所依赖的定级没有找到
在实践, 错误 可能扔 静静地, e.g,你提出一个定时器的任务,并在定时器的任务,它将引发 错误, ,而在大多数情况下,您的节目只有抓住 异常.那么 计时器 主循环结束,没有任何信息。类似的错误NoClassDefFoundError是 ExceptionInInitializerError, 当你静初始化或初的静态变量会引发一个例外。
ClassNotFoundException 是一种检查的例外发生在我们告诉JVM载的一类通过其串名使用类。forName()或类装入器。findSystemClass()或类装入器。loadClass()方法,并提到类中找不到类路径。
大多数时候,这一例外发生的时候你尝试运行的应用程序没有更新的类路径所需的罐子文件。例如,你可能已经看到这种异常做JDBC代码连接到你的数据库。e.MySQL但类路径没有罐子里。
NoClassDefFoundError 错误发生时JVM试图载入特别类的一部分代码的执行(为部分的一个正常的方法调用的一部分或作为创建一个实例,使用的新的关键词)和这类不存在类路径,但是目前在编制时间,因为为了执行你的计划你需要来编制它如果你试图使用了一类不存编译器将提高编辑错误。
下面简要说明
你可以阅读 一切有关ClassNotFoundException Vs NoClassDefFoundError 更多的细节。
我提醒自己以下一次又一次的时候我需要刷新
ClassNotFoundException
类层次
ClassNotFoundException extends ReflectiveOperationException extends Exception extends Throwable
在调试
- 所需要的罐子,类缺失类路径。
- 验证所需的所有罐子是在类路径jvm。
NoClassDefFoundError
类层次
NoClassDefFoundError extends LinkageError extends Error extends Throwable
在调试
- 问题载入一类的动态,这是编制正确的
- 问题静块构造,初始化()方法的依赖类和实际错误是包裹通过多层[尤其是在使用弹簧的、休眠实际的例外是包裹,你会得到NoClassDefError]
- 当你面对"ClassNotFoundException"下一个静态块的依赖类
- 问题的版本。这种情况发生时你有两个版本v1,v2的同类在不同的罐子/软件包,将其编制成功地使用v1和v2被装载在运行时,它并不拥有相关方法/var你会看到这样的例外。[我有一次解决这个问题通过去除重复的log4j相关类在多个罐子中出现的类路径]
ClassNotFoundException和NoClassDefFoundError时出现的特定类是没有发现在运行时间。然而,它们发生在不同的情况。
ClassNotFoundException是一个例外发生的时候你尽量负荷的一类在运行时间使用类。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();
}
}
当你汇编上述程序中,有两个。类文件将会产生。一个是A.class 和另外一个是B.class.如果你移除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)