The difference from the Java API Specifications is as follows.
Thrown when an application tries to load in a class through its string name using:
- The
forName
method in classClass
.- The
findSystemClass
method in classClassLoader
.- The
loadClass
method in classClassLoader
.but no definition for the class with the specified name could be found.
For NoClassDefFoundError
:
Thrown if the Java Virtual Machine or a
ClassLoader
instance tries to load in the definition of a class (as part of a normal method call or as part of creating a new instance using the new expression) and no definition of the class could be found.The searched-for class definition existed when the currently executing class was compiled, but the definition can no longer be found.
So, it appears that the NoClassDefFoundError
occurs when the source was successfully compiled, but at runtime, the required class
files were not found. This may be something that can happen in the distribution or production of JAR files, where not all the required class
files were included.
As for ClassNotFoundException
, it appears that it may stem from trying to make reflective calls to classes at runtime, but the classes the program is trying to call is does not exist.
The difference between the two is that one is an Error
and the other is an Exception
. WithNoClassDefFoundError
is an Error
and it arises from the Java Virtual Machine having problems finding a class it expected to find. A program that was expected to work at compile-time can't run because of class
files not being found, or is not the same as was produced or encountered at compile-time. This is a pretty critical error, as the program cannot be initiated by the JVM.
On the other hand, the ClassNotFoundException
is an Exception
, so it is somewhat expected, and is something that is recoverable. Using reflection is can be error-prone (as there is some expectations that things may not go as expected. There is no compile-time check to see that all the required classes exist, so any problems with finding the desired classes will appear at runtime.
首先:
ClassNotFoundException直接继承与Exception,它是一个checked的异常。
NoClassDefFoundErr 继承自Error->LinkageError ,它是一个unchecked的异常。
下面让我们看一下两个异常在API文档中的说明:
当应用尝试用字符串名称通过下面的方法装载一个类时这个类的定义却没有找到时会抛出的异常。
Class.forName
ClassLoader.findSystemClass
ClassLoader.loadClass
NoClassDefFoundErr:
当JVM或者ClassLoader实例尝试装载一个类的定义(这通常是一个方法调用或者new表达式创建一个实例过程的一部分)而这个类定义并没有找时所抛出的错误。
当编译的时候可以找到这个类的定义,但是以后这个类不再存在。
ClassNotFoundException异常只出现在你的应用程序主动的装载类的过程中,这个异常很多时候出现在我们的应用框架在初始化或者运行中动态装载已配置的类的过程中。这种情况下我们应该首先检查我们的配置或者参数是否错误,是否企图装载一个并不存在的类,如果配置没有错误,我们就应该查看Classpath是否配置错误而导致ClassLoader无法找到这个类,也应该检查要装载的类是否在一个jar包中而我们在引入这个jar包的过程中是否有遗漏或错误(这里jar包的版本也是一个需要格外注意的问题,很多时候混乱的jar包版本会造成太多的麻烦)。
NoClassDefFoundErr异常一般出现在我们编译环境和运行环境不一致的情况下,就是说我们有可能在编译过后更改了Classpath或者jar包所以导致在运行的过程中JVM或者ClassLoader无法找到这个类的定义。
不含包层次的HelloWorld.java
public classHelloWorld
保存在E:\java\src下,命令行下,改变当前路径到:E:\java\src,使用javac命令编译:
E:\java\src>javac HelloWorld.java
运行:
E:\java\src>java HelloWorld
屏幕打印出:
Hello World!
初学者常犯的错误
1.运行时,带了.class后缀
如果你试图使用如下命令:
E:\java\src>javaHelloWorld.class
系统会误认为你运行的是HelloWorld包下的名为class的类文件,会到系统的CLASSPATH下(一般都包括当前目录)企图寻找HelloWorld.class.class这样的类,这样的类当然不存在了;并且也不可能存在,因为class是关键字,不能作为一个类的名字。所以会报如下错误信息:
Exception in thread "main"java.lang.NoClassDefFoundError: HelloWorld/class
2.文件名大小写错误
对于像Windows这样的系统,编译时可以不关心大小写。比如编译HelloWorld.java时,也可以使用:
E:\java\src>javachelloworld.java
也可以编译通过,但产生的类文件仍然是和源文件相符的:HelloWorld.class。
但在运行时一定要注意大小写,比如试图使用如下命令运行:
E:\java\src>javahelloworld
将报类似于1中的错误:
Exception in thread "main"java.lang.NoClassDefFoundError: helloworld (wrong name:HelloWorl