Answers:
与Java API规范的区别如下。
当应用程序尝试使用其字符串名称通过其字符串名称加载类时抛出:
forName
课堂教学中的方法Class
。findSystemClass
课堂教学中的方法ClassLoader
。loadClass
课堂教学中的方法ClassLoader
。但是找不到具有指定名称的类的定义。
如果Java虚拟机或
ClassLoader
实例尝试加载类的定义(作为常规方法调用的一部分或使用新表达式创建新实例的一部分)而抛出,则找不到该类的定义。当前编译的类在编译时就存在搜索到的类定义,但不再可以找到该定义。
因此,似乎NoClassDefFoundError
在成功编译源代码时发生了,但是在运行时class
找不到所需的文件。这可能是在分发或生成JAR文件时发生的,其中未class
包含所有必需的文件。
至于ClassNotFoundException
,似乎是由于试图在运行时对类进行反射性调用而引起的,但程序尝试调用的类不存在。
两者之间的区别在于,一个是an Error
,另一个是an Exception
。with NoClassDefFoundError
是Error
,它源自Java虚拟机在查找预期要找到的类时遇到问题。由于class
找不到文件,或者与编译时生成或遇到的文件不同,预期无法在编译时运行的程序无法运行。这是一个非常严重的错误,因为该程序无法由JVM启动。
另一方面,ClassNotFoundException
是Exception
,因此在某种程度上是可以预期的,并且可以恢复。使用反射可能容易出错(因为有些期望可能不会按预期进行。没有进行编译时检查以确保所有必需的类都存在,因此查找所需类的任何问题都会在运行时出现。
NoClassDefFoundError
通常在类的静态块或静态字段初始化出现问题(引发异常)时发生,因此无法成功初始化类。
Error
,另一个是一个Exception
。:)
当ClassLoader未找到报告的类时,将引发ClassNotFoundException。这通常意味着CLASSPATH中缺少该类。这也可能意味着该类正试图从另一个已加载到父类加载器中的类中加载,因此子类加载器中的类不可见。在更复杂的环境(例如App Server)中工作时,有时就是这种情况(WebSphere臭名昭著的类加载器问题)。
人们常常会混淆java.lang.NoClassDefFoundError
,java.lang.ClassNotFoundException
但是有一个重要的区别。例如一个异常(实际上java.lang.NoClassDefFoundError
是一个错误,因为它是java.lang.Error的子类)
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文件中搜索该类的根目录路径。
当您的代码运行“ new Y()”并且找不到Y类时,会发生NoClassDefFoundError(NCDFE)。
可能只是像其他注释所建议的那样,您的类加载器中缺少Y,但也可能是Y类未签名或具有无效的签名,或者Y是由您的代码不可见的其他类加载器加载的,或者甚至Y取决于Z,由于上述任何原因,Z均无法加载。
如果发生这种情况,那么JVM会记住加载X(NCDFE)的结果,并且每次您请求Y时它都会简单地抛出一个新的NCDFE,而不会告诉您原因:
A类{ 静态类b {} 公共静态void main(String args []){ System.out.println(“首次尝试新b():”); 尝试{new b(); } catch(Throwable t){t.printStackTrace();} System.out.println(“ \ n第二次尝试new b():”); 尝试{new b(); } catch(Throwable t){t.printStackTrace();} } }
将其另存为a.java
该代码只是尝试两次实例化一个新的“ b”类,除此之外,它没有任何错误,并且没有任何作用。
使用编译代码javac a.java
,然后通过调用运行a java -cp . a
-它应该只打印出两行文本,并且可以正常运行而不会出错。
然后删除“ a $ b.class”文件(或将其填充为垃圾,或在其上复制a.class)以模拟丢失或损坏的类。这是发生了什么:
第一次尝试new b(): java.lang.NoClassDefFoundError:a $ b 在a.main(a.java:5) 引起原因:java.lang.ClassNotFoundException:a $ b 在java.net.URLClassLoader $ 1.run(URLClassLoader.java:200) 在java.security.AccessController.doPrivileged(本机方法) 在java.net.URLClassLoader.findClass(URLClassLoader.java:188) 在java.lang.ClassLoader.loadClass(ClassLoader.java:307) 在sun.misc.Launcher $ AppClassLoader.loadClass(Launcher.java:301) 在java.lang.ClassLoader.loadClass(ClassLoader.java:252) 在java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320) ...还有1个 第二次尝试new b(): java.lang.NoClassDefFoundError:a $ b 在a.main(a.java:7)
第一次调用会导致ClassNotFoundException(当无法找到类时由类加载器抛出),该类必须包装在未经检查的NoClassDefFoundError中,因为所讨论的代码(new b()
)应该可以正常工作。
当然,第二次尝试也会失败,但是您可以看到包装的异常不再存在,因为ClassLoader似乎记得失败的类加载器。您只会看到NCDFE,而完全不知道真正发生了什么。
因此,如果您看到无根本原因的NCDFE,则需要查看是否可以追溯到第一次加载类时才查找错误原因。
-verbose
或类似的选项(取决于特定的JVM)运行JVM怎么样?也许是-verbose:class
,-verbose:class:jni
如果使用JNI,但是我不确定语法。如果有用的话,也许您可以显示结果。
-verbose:class
也不-verbose:jni
提供与缺少的类相关的任何其他输出。
-verbose:class:jni
是错误的:必须指定两个单独的选项:-verbose:class -verbose:jni
。)
来自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虚拟机尝试加载类的定义并且找不到该类的定义,则抛出该错误。
-verbose
或类似的选项(取决于特定的JVM)运行JVM怎么样?也许是-verbose:class
,-verbose:class:jni
如果使用JNI,但是我不确定语法。
-verbose:class:jni
是错误的,但是您可以传递两个单独的选项:-verbose:class -verbose:jni
。
尝试通过String引用加载类时,抛出ClassNotFoundException。例如,Class.forName()中的参数to是一个String,这增加了将无效二进制名称传递给类加载器的可能性。
当遇到可能无效的二进制名称时,将引发ClassNotFoundException;例如,如果类名带有'/'字符,则势必会收到ClassNotFoundException。当直接引用的类在类路径上不可用时,也会引发该错误。
另一方面,抛出NoClassDefFoundError
简而言之,当类加载器无法找到或加载类定义时,通常会在加载以前不存在的类的new()语句或方法调用上引发NoClassDefFoundError(与ClassNotFoundException的基于字符串的类加载相反) s)。
最终,当无法加载类时,由ClassLoader实现抛出ClassNotFoundException实例。大多数自定义类加载器实现都执行此操作,因为它们扩展了URLClassLoader。通常,类加载器不会在任何方法实现上显式抛出NoClassDefFoundError-通常从HotSpot编译器中的JVM抛出此异常,而不是由类加载器本身抛出。
使用名称本身,我们可以轻松地识别一个来自
Exception
和另一个来自Error
。
异常:程序执行期间发生异常。程序员可以通过try catch块来处理这些异常。我们有两种类型的例外。在编译时抛出的已检查异常。运行时引发的运行时异常,这些异常通常是由于编程错误而发生的。
错误:这些根本不是例外,这超出了程序员的范围。这些错误通常由JVM引发。
区别:
ClassNotFoundException:
ClassNotFoundException
。ClassNotFoundException
是直接从java.lang.Exception
类派生的已检查异常,您需要为其提供显式处理ClassNotFoundException
当通过在运行时使用ClassLoader.loadClass(),Class.forName()和ClassLoader.findSystemClass()提供类名来显式加载类时,会出现此错误。NoClassDefFoundError:
NoClassDefFoundError
NoClassDefFoundError
是从LinkageError
类派生的Error ,用于指示错误情况,其中某个类对某个其他类具有依赖项,并且该类在编译后发生了不兼容的更改。 NoClassDefFoundError
是由于该类的方法调用或任何变量访问而隐式加载类的结果。相似之处:
NoClassDefFoundError
和ClassNotFoundException
都与运行时类的不可用性有关。 ClassNotFoundException
和NoClassDefFoundError
都与Java类路径有关。给定Class loader sussystem操作:
这篇文章对我的理解有所帮助:http : //docs.oracle.com/javase/specs/jvms/se7/html/jvms-5.html
如果在类加载期间发生错误,则必须在程序中直接或间接使用要加载的类或接口的位置上抛出LinkageError子类的实例。
如果Java虚拟机曾经在验证(第5.4.1节)或解析(第5.4.3节)(但未初始化(第5.5节))期间尝试加载类C,则尝试启动用于加载C的类加载器抛出ClassNotFoundException的实例,那么Java虚拟机必须抛出NoClassDefFoundError的实例,其原因是ClassNotFoundException的实例。
因此,ClassNotFoundException是NoClassDefFoundError的根本原因。
而一个NoClassDefFoundError的是类加载错误的特殊情况下,发生在链接的一步。
在实践中添加一个可能的原因:
实际上,可能会默默地抛出Error,例如,您提交了一个计时器任务,并且在计时器任务中它抛出Error,而在大多数情况下,您的程序仅捕获Exception。然后,Timer主循环结束,没有任何信息。当您的静态初始值设定项或静态变量的初始值设定项引发异常时,与NoClassDefFoundError相似的错误是ExceptionInInitializerError。
ClassNotFoundException是一个经过检查的异常,当我们告诉JVM使用Class.forName()或ClassLoader.findSystemClass()或ClassLoader.loadClass()方法通过其字符串名称加载类并且在类路径中找不到所提到的类时,将发生ClassNotFoundException。
大多数情况下,当您尝试运行应用程序而不用必需的JAR文件更新类路径时,就会发生此异常。例如,当您执行JDBC代码连接到数据库即MySQL时,您可能已经看到此异常,但是您的类路径没有JAR。
当JVM尝试加载代码执行过程中的特定类(作为常规方法调用的一部分或使用new关键字创建实例的一部分)并且该类不存在于您的类路径中时,就会发生NoClassDefFoundError错误。出现在编译时,因为要执行您的程序,您需要对其进行编译,并且如果尝试使用不存在的类,则编译器将引发编译错误。
以下是简要说明
您可以阅读有关ClassNotFoundException的所有内容和NoClassDefFoundError的更多信息。
当我需要刷新时,我会一次又一次提醒自己
ClassNotFoundException
类层次结构
ClassNotFoundException extends ReflectiveOperationException extends Exception extends Throwable
调试时
NoClassDefFoundError
类层次结构
NoClassDefFoundError extends LinkageError extends Error extends Throwable
调试时
当在运行时找不到特定的类时,会发生ClassNotFoundException和NoClassDefFoundError,但是它们发生在不同的情况下。
ClassNotFoundException是一种异常,当您尝试在运行时使用Class.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();
}
}
当您编译上述程序时,将生成两个.class文件。一个是A.class,另一个是B.class。如果删除A.class文件并运行B.class文件,则Java Runtime System将抛出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)
-verbose
(例如-verbose:class -verbose:jni
)帮助下运行JVM –但是mogsie在他们的回答下报告说,这没有提供额外的有用信息:(