在本文中,我们将了解NoClassDefFoundError
和ClassNotFoundException
之间的区别。这是增加java异常知识的问题之一。
我们将研究NoClassDefFoundError
和ClassNotFoundException
的区别、相似性和示例。
NoClassDefFoundError和ClassNotFoundException之间的差异
Error与Exception:主要区别在于它们的名称。您可以看到NoClassDefFoundError
是Error,它是从LinkageError
派生的。这意味着NoClassDefFoundError
在链接过程中发生,程序无法运行,但编译成功。
ClassNotFoundException
是从ReflectiveOperationException
派生的异常,它发生在运行时。
不可恢复vs可恢复:NoClassDefFoundError
指try/catch/finally块未处理的不可恢复情况。ClassNotFoundException
是选中的异常,需要使用try/catch/finally块进行处理。
抛出时的情况以及如何避免这些情况:出现ClassNotFoundException
时的情况是应用程序试图通过其字符串名称在类中加载,使用:
- 类中的
forName
方法; - 类装入器中的
findSystemClass
方法; - 类装入器中的
loadClass
方法;
但找不到具有指定名称的类的定义。
为避免此异常,需要确保:
- 类在与该类关联的类装入器的逻辑类路径中可用;
- 类加载器API是否正确使用
Class.forName()
; - 被加载的类的依赖类对类加载器可见;
- 等。
出现NoClassDefFoundError
时的情况是Java虚拟机或ClassLoader
实例试图加载类的定义(作为普通方法调用的一部分或使用新表达式创建新实例的一部分),但找不到类的定义(类的格式不正确,类的版本号不匹配等)。
类无法加载,原因如下:
- 未能加载依赖类;
- 依赖类格式错误;
- 类的版本号不正确;
- 类已经加载到另一个类加载器中;
- 等。
NoClassDefFoundError和ClassNotFoundException示例
如果我们有以下代码:
public class NoClassDefFoundErrorExample {
public static void main(String[] args) {
A a = new A();
}
}
public class A extends B {
}
public class B {
}
现在如果我们从类路径编译后删除B.class
。
执行此代码的结果是:线程“main
”中出现异常java.lang.NoClassDefFoundError: B
。
如下图所示:
public class ClassNotFoundExceptionExample {
public static void main(String[] args) throws ClassNotFoundException {
Class.forName("com.example.Class1");
}
}
执行此代码的结果是:
线程“main”中出现异常java.lang.ClassNotFoundException: com.example.Class1
因为类加载器无法加载com.example.Class1
类。
概述:ClassNotFoundException和NoClassDefFoundError之间的区别
ClassNotFoundException | NoClassDefFoundError | |
Exception vs Error | CheckedException | Error |
抛出阶段 | 运行时 | 链接 |
派生 | ReflectiveOperationException | LinkageError |
不可恢复vs可恢复 | 可恢复 | 不可恢复 |
需要try/catch/finally块 | 是 | 否 |
抛出异常场景 |
应用程序试图加载到类中通过它的字符串名,但不是具有指定找不到名称 |
ClassLoader实例尝试加载在类的定义中找不到类的定义 |
总结:
如果我们看看oracle文档http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-5.html,我们可以发现:
如果在类加载期间发生错误,则LinkageError
子类的实例必须在程序中(直接或间接)使用被加载的类或接口的某个点抛出。
如果Java虚拟机曾经尝试在验证或解析(而不是初始化)期间加载类C,并且用于启动C加载的类加载器抛出ClassNotFoundException
实例,则Java虚拟机必须抛出NoClassDefFoundError
实例,其原因是ClassNotFoundException
的实例。
从这个解释我们可以得出这样的结论:ClassNotFoundException
是NoClassDefFoundError
的根本原因,而NoClassDefFoundError
是类型加载错误的一个特例,发生在链接步骤。
除特别注明外,本站所有文章均为老K的Java博客原创,转载请注明出处来自https://javakk.com/1534.html
暂无评论