NoClassDefFoundError
和ClassNotFoundException
什么区别? html
是什么致使它们被抛出? 如何解决? java
在修改现有代码以包含新的jar文件时,我常常遇到这些throwables。 我在客户端和服务器端都经过Webstart分发了一个Java应用程序。 数据库
我遇到的可能缘由: apache
build.xml
中的软件包 今天,当我遇到这些问题时,我采起了走错一步的方法来使事情顺利进行。 我须要更多的清晰度和理解。 api
NoClassDefFoundError
基本上是一个连接错误。 当您尝试实例化一个对象时会发生这种状况(静态地使用“ new”),而在编译过程当中则找不到该对象。 服务器
ClassNotFoundException
更通用,是当您尝试使用不存在的类时的运行时异常。 例如,您在函数中具备接受接口的参数,而且有人传入实现该接口的类,但您无权访问该类。 它还介绍了动态类加载的状况,例如使用loadClass()
或Class.forName()
。 函数
与Java API规范的区别以下。 网站
对于ClassNotFoundException
: ui
当应用程序尝试使用其字符串名称经过其字符串名称加载类时抛出: spa
- 类
Class
的forName
方法。- 类
ClassLoader
的findSystemClass
方法。- 类
ClassLoader
的loadClass
方法。但找不到具备指定名称的类的定义。
若是Java虚拟机或
ClassLoader
实例尝试加载类的定义(做为常规方法调用的一部分或使用新表达式建立新实例的一部分)而抛出,则ClassLoader
的定义。当前正在编译的类在编译时就存在搜索到的类定义,可是没法再找到该定义。
所以,彷佛在成功编译源代码时发生了NoClassDefFoundError
,可是在运行时未找到所需的class
文件。 这多是在JAR文件的分发或生产中可能发生的状况,其中并未包括全部必需的class
文件。
至于ClassNotFoundException
,彷佛是因为试图在运行时对类进行反射性调用而引发的,但程序尝试调用的类不存在。
二者的区别在于,一个是Error
,另外一个是Exception
。 使用NoClassDefFoundError
是一个Error
,它是因为Java虚拟机在查找其指望查找的类时遇到问题而引发的。 因为找不到class
文件,或者与编译时生成或遇到的class
文件不一样,预期没法在编译时工做的程序没法运行。 这是一个很是严重的错误,由于该程序没法由JVM启动。
另外一方面, ClassNotFoundException
是Exception
,所以在某种程度上是能够预期的,而且能够恢复。 使用反射是容易出错的(由于有些指望可能不会按预期进行。没有编译时检查以确保全部必需的类都存在,所以查找所需类的任何问题都会在运行时出现。
尝试经过String引用加载类时,抛出ClassNotFoundException 。 例如,Class.forName()中的参数to是一个字符串,这增长了将无效二进制名称传递给类加载器的可能性。
当遇到可能无效的二进制名称时,将引起ClassNotFoundException; 例如,若是类名带有'/'字符,则势必会收到ClassNotFoundException。 当直接引用的类在类路径上不可用时,也会抛出该错误。
另外一方面,抛出NoClassDefFoundError
简而言之,当类加载器没法找到或加载类定义时,一般会在加载之前不存在的类的new()语句或方法调用上引起NoClassDefFoundError(与ClassNotFoundException的基于字符串的类加载相反) s)。
最终,当没法加载类时,由ClassLoader实现抛出ClassNotFoundException实例。 大多数自定义类加载器实现都执行此操做,由于它们扩展了URLClassLoader。 一般,类加载器不会在任何方法实现上显式抛出NoClassDefFoundError-一般从HotSpot编译器中的JVM抛出此异常,而不是由类加载器自己抛出。
当ClassLoader未找到报告的类时,将引起ClassNotFoundException。 这一般意味着CLASSPATH中缺乏该类。 这也可能意味着该类正试图从另外一个已加载到父类加载器中的类中加载,所以子类加载器中的类不可见。 在更复杂的环境(例如App Server)中工做时,有时会是这种状况(WebSphere臭名昭著的类加载器问题)。
人们一般倾向于将java.lang.NoClassDefFoundError
与java.lang.ClassNotFoundException
混淆,可是有一个重要的区别。 例如一个异常(其实是一个错误,由于java.lang.NoClassDefFoundError
是java.lang.NoClassDefFoundError
的子类)
java.lang.NoClassDefFoundError: org/apache/activemq/ActiveMQConnectionFactory
这并不意味着ActiveMQConnectionFactory类不在CLASSPATH中。 其实是相反的。 这意味着ClassLoader找到了ActiveMQConnectionFactory类,可是在尝试加载该类时,在读取类定义时遇到了错误。 当所涉及的类具备使用ClassLoader找不到的类的静态块或成员时,一般会发生这种状况。 所以,要找到罪魁祸首,请查看相关类的源(在本例中为ActiveMQConnectionFactory),并使用静态块或静态成员查找代码。 若是您无权访问源,则只需使用JAD对其进行反编译。
在检查代码时,假设您发现以下所示的代码行,请确保CLASSPATH中的类SomeClass。
private static SomeClass foo = new SomeClass();
提示:要找出一个类所属的jar,可使用网站jarFinder。 这使您可使用通配符指定类名,并在其jar数据库中搜索该类。 jarhoo容许您执行相同的操做,但再也不无偿使用。
若是要在本地路径中找到类所属的jar,可使用jarscan( http://www.inetfeedback.com/jarscan/ )之类的实用程序。 您只需指定要查找的类以及您但愿它开始在jar和zip文件中搜索该类的根目录路径。
来自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 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虚拟机尝试加载类的定义而且找不到该类的定义,则抛出该异常。