一、ClassNotFoundException
ClassNotFoundException 是一个异常(Exception),其产生的原因是:Java支持使用 Class.forName 方法来动态地加载类,任意一个类的类名如果被作为参数传递给这个方法都将导致该类被加载到 JVM 中。如果这个类在类路径中没有被找到,那么此时就会在运行时抛出 ClassNotFoundException 异常。
要解决这个问题,就要确保所需的类连同它依赖的包存在于类路径中。当 Class.forName 被调用的时候,类加载器会查找类路径中的类,如果找到了那么这个类就会被成功加载,如果没找到,那么就会抛出ClassNotFountException。
除了 Class.forName,ClassLoader.loadClass、ClassLOader.findSystemClass 在动态加载类到内存中的时候也可能会抛出这个异常。
另外还有一个导致 ClassNotFoundException 的原因就是:当一个类已经某个类加载器加载到内存中了,此时另一个类加载器又尝试着动态地从同一个包中加载这个类。
由于类的动态加载在某种程度上是被开发者所控制的,所以他可以选择 catch 这个异常然后采取相应的补救措施。
二、NoClassDefFoundError
NoClassDefFoundError是一个错误(Error),其产生的原因是:当 Java 虚拟机 或 ClassLoader 实例试图在类的定义中加载(作为通常方法调用的一部分,或者是使用 new 来创建新的对象)时,却找不到类的定义(要查找的类在编译的时候是存在的,运行的时候却找不到了),抛出此异常。
即当前执行的类被编译时,所搜索的类定义存在,但无法再找到该定义。
这个错误往往是你使用 new 操作符来创建一个新的对象,但却找不到该对象对应的类。这个时候就会导致NoClassDefFoundError
由于 NoClassDefFoundError 是有 JVM 引起的,所以不应该尝试捕捉这个错误。
三、区别
- NoClassDefFoundError 是 JVM 引起的错误,是 unchecked,未经检查的。因此不会使用 try-catch 或者 finally 语句块;ClassNotFoundException 是受检异常,因此需要 try-catch 语句块或者 try-finally 语句块包围,否则会导致编译错误。
- NoClassDefFoundError 是链接错误,发生在链接阶段,当解析引用找不到对应的类,就会触发;而 ClassNotFoundException 是发生在运行时的异常。
- 调用 Class.forName()、ClassLoader.findClass() 和 ClassLoader.loadClass() 等方法时可能会引起 java.lang.ClassNotFoundException