什么缘由致使NoClassDefFoundError和ClassNotFoundException之间有什么区别?

NoClassDefFoundErrorClassNotFoundException什么区别? html

是什么致使它们被抛出? 如何解决? java

在修改现有代码以包含新的jar文件时,我常常遇到这些throwables。 我在客户端和服务器端都经过Webstart分发了一个Java应用程序。 数据库

我遇到的可能缘由: apache

  1. 客户端代码未包含在build.xml中的软件包
  2. 咱们正在使用的新jar缺乏运行时类路径
  3. 版本与先前的jar冲突

今天,当我遇到这些问题时,我采起了走错一步的方法来使事情顺利进行。 我须要更多的清晰度和理解。 api


#1楼

NoClassDefFoundError基本上是一个连接错误。 当您尝试实例化一个对象时会发生这种状况(静态地使用“ new”),而在编译过程当中则找不到该对象。 服务器

ClassNotFoundException更通用,是当您尝试使用不存在的类时的运行时异常。 例如,您在函数中具备接受接口的参数,而且有人传入实现该接口的类,但您无权访问该类。 它还介绍了动态类加载的状况,例如使用loadClass()Class.forName()函数


#2楼

与Java API规范的区别以下。 网站

对于ClassNotFoundExceptionui

当应用程序尝试使用其字符串名称经过其字符串名称加载类时抛出: spa

  • ClassforName方法。
  • ClassLoaderfindSystemClass方法。
  • ClassLoaderloadClass方法。

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

对于NoClassDefFoundError

若是Java虚拟机或ClassLoader实例尝试加载类的定义(做为常规方法调用的一部分或使用新表达式建立新实例的一部分)而抛出,则ClassLoader的定义。

当前正在编译的类在编译时就存在搜索到的类定义,可是没法再找到该定义。

所以,彷佛在成功编译源代码时发生了NoClassDefFoundError ,可是在运行时未找到所需的class文件。 这多是在JAR文件的分发或生产中可能发生的状况,其中并未包括全部必需的class文件。

至于ClassNotFoundException ,彷佛是因为试图在运行时对类进行反射性调用而引发的,但程序尝试调用的类不存在。

二者的区别在于,一个是Error ,另外一个是Exception 。 使用NoClassDefFoundError是一个Error ,它是因为Java虚拟机在查找其指望查找的类时遇到问题而引发的。 因为找不到class文件,或者与编译时生成或遇到的class文件不一样,预期没法在编译时工做的程序没法运行。 这是一个很是严重的错误,由于该程序没法由JVM启动。

另外一方面, ClassNotFoundExceptionException ,所以在某种程度上是能够预期的,而且能够恢复。 使用反射是容易出错的(由于有些指望可能不会按预期进行。没有编译时检查以确保全部必需的类都存在,所以查找所需类的任何问题都会在运行时出现。


#3楼

尝试经过String引用加载类时,抛出ClassNotFoundException 。 例如,Class.forName()中的参数to是一个字符串,这增长了将无效二进制名称传递给类加载器的可能性。

当遇到可能无效的二进制名称时,将引起ClassNotFoundException; 例如,若是类名带有'/'字符,则势必会收到ClassNotFoundException。 当直接引用的类在类路径上不可用时,也会抛出该错误。

另外一方面,抛出NoClassDefFoundError

  • 当类的实际物理表示形式-.class文件不可用时,
  • 或已将类加载到其余类加载器中(一般是父类加载器会加载该类,所以没法再次加载该类),
  • 或若是找到了不兼容的类定义-类文件中的名称与请求的名称不匹配,
  • 或(最重要的)是否没法找到和加载相关类。 在这种状况下,可能已经找到并加载了直接引用的类,可是从属类不可用或没法加载。 在这种状况下,能够经过Class.forName或等效方法加载直接引用的类。 这代表连接失败。

简而言之,当类加载器没法找到或加载类定义时,一般会在加载之前不存在的类的new()语句或方法调用上引起NoClassDefFoundError(与ClassNotFoundException的基于字符串的类加载相反) s)。

最终,当没法加载类时,由ClassLoader实现抛出ClassNotFoundException实例。 大多数自定义类加载器实现都执行此操做,由于它们扩展了URLClassLoader。 一般,类加载器不会在任何方法实现上显式抛出NoClassDefFoundError-一般从HotSpot编译器中的JVM抛出此异常,而不是由类加载器自己抛出。


#4楼

当ClassLoader未找到报告的类时,将引起ClassNotFoundException。 这一般意味着CLASSPATH中缺乏该类。 这也可能意味着该类正试图从另外一个已加载到父类加载器中的类中加载,所以子类加载器中的类不可见。 在更复杂的环境(例如App Server)中工做时,有时会是这种状况(WebSphere臭名昭著的类加载器问题)。

人们一般倾向于将java.lang.NoClassDefFoundErrorjava.lang.ClassNotFoundException混淆,可是有一个重要的区别。 例如一个异常(其实是一个错误,由于java.lang.NoClassDefFoundErrorjava.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文件中搜索该类的根目录路径。


#5楼

来自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虚拟机尝试加载类的定义而且找不到该类的定义,则抛出该异常。

相关文章
相关标签/搜索