NoClassDefFoundError和ClassNotFoundException的区别
-
从两个异常的名称上来看,一个是错误,一个是异常。
-
两者都是在程序运行过程中,去加载某个类时没有找到对应的类而产生的异常。
-
NoClassDefFoundError是指编译时没有问题,而在运行时却找不到类的定义,也就是说类在编译时有,但在运行时却找不到。它主要在程序运行过程中JVM主动去加载某个类却找不到类定义时抛出。比如调用了某个类的静态方法、通过new关键字创建某个类的实例等。Java源码中对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. Since: JDK1.0 Author: unascribed
-
ClassNotFoundException是在程序中主动要求加载某个类的时候没有找到相关的类定义时抛出的异常,主要是通过如下三个方法Class.forName(String className)、ClassLoader.findSystemClass()、ClassLoader.loadClass()。当使用这几个方法在程序中主动去加载一个类时,由于指定的是类的全限定名,即使是全限定名代表的类不存在,也可以通过编译,直到程序运行时才发现类找不到。Java源码中对ClassNotFoundException的注释如下:
Thrown when an application tries to load in a class through its string name using: The forName method in class Class. The findSystemClass method in class ClassLoader . The loadClass method in class ClassLoader. but no definition for the class with the specified name could be found. As of release 1.4, this exception has been retrofitted to conform to the general purpose exception-chaining mechanism. The "optional exception that was raised while loading the class" that may be provided at construction time and accessed via the getException() method is now known as the cause, and may be accessed via the Throwable.getCause() method, as well as the aforementioned "legacy method."
-
测试用例如下:
类结构如下:
ExceptionTest:
public class ExceptionTest {
/**
* 用来测试NoClassDefFoundError
* 和 ClassNotFoundException
*/
public static void main(String[] args) throws ClassNotFoundException, InterruptedException {
System.out.println("program start");
int i = 0;
//之所以写在循环里,并且循环到第10次时才加载,是让我在程序加载类前有时间去删除类的class文件
while(true){
if(i == 10){
/**
* Class.forName是在程序中主动去加载某个类,在下面两种情况下会抛ClassNotFoundException
* 1:在加载前把ExceptionClass的class文件删除
* 2:Class.forName的参数写成一个根本不存在的类,如test.exception.ExceptionClass2
*/
//Class.forName("test.exception.ExceptionClass");
/**
* 通过new是JVM在运行过程中主动加载类。如果在程序启动后,运行这句代码前把ExceptionClass的class文件删了,就会报NoClassDefFoundError
*/
new ExceptionClass();
break;
}else{
TimeUnit.SECONDS.sleep(1);
i++;
}
}
}
}
ExceptionClass:
public class ExceptionClass {
static {
System.out.println("In ExceptionClass");
}
}