ClassNotFoundException vs NoClassDefFoundError
最后修改:2019年10月3日
1.介绍
这两个类未发现例外和NoClassDefFoundError当JVM在类路径上找不到请求的类时发生。虽然他们看起来很熟悉,但他们之间有一些核心的区别。
在本教程中,我们将讨论它们出现的原因及其解决方案。
2.类未发现例外
类未发现例外是一个检查异常,当应用程序试图通过类的完全限定名加载类,但在类路径上找不到类的定义时发生。
这主要发生在试图装入类使用forname (),ClassLoader.loadClass ()或ClassLoader.findSystemClass ()。因此,我们要格外小心java.lang.ClassNotFoundException当工作与反思。
例如,让我们尝试在不添加必要的依赖项的情况下加载JDBC驱动程序类,这将使我们ClassNotFoundException:
@Test(expected = ClassNotFoundException.class) public void givenNoDrivers_whenLoadDriverClass_thenClassNotFoundException() throws ClassNotFoundException {Class.forName("oracle.jdbc.driver. oracle ");}
3.NoClassDefFoundError
NoClassDefFoundError是一个致命的错误。当JVM无法找到类的定义,而试图:
- 实例化一个类新关键字
- 用方法调用装入类
当编译器可以成功编译类,但Java运行时无法定位类文件时,就会发生错误。它通常发生在执行静态块或初始化类的静态字段时出现异常时,因此类初始化失败。
让我们考虑一个场景,它是再现问题的一种简单方法。ClassWithInitErrors初始化抛出异常。所以,当我们尝试创建一个对象ClassWithInitErrors,它把ExceptionInInitializerError。
如果我们试图再次加载相同的类,我们会得到NoClassDefFoundError:
public class classwithiniterors {static int data = 1 / 0;}
public class noclassdeffounderroreexample {public classwithiterors getclasswithiterors () {classwithiterors测试;try {test = new classwithiterors ();} catch(可抛出的t) {System.out.println(t);} test = new classwithiterors ();回归测试;}}
让我们为这个场景写一个测试用例:
@Test(expected = NoClassDefFoundError.class) public void givenInitErrorInClass_whenloadClass_thenNoClassDefFoundError() {noclassdeffounderroreexample sample = new noclassdeffounderroreexample ();sample.getClassWithInitErrors ();}
4.决议
有时,诊断和修复这两个问题会非常耗时。这两个问题的主要原因是类文件(在类路径中)在运行时不可用。
让我们看看在处理这两种情况时可以考虑的几种方法:
- 我们需要确保类路径中包含该类的class或jar是否可用。如果没有,我们需要添加它
- 如果它在应用程序的类路径上可用,那么很可能类路径正在被覆盖。要解决这个问题,我们需要找到应用程序使用的确切类路径
- 另外,如果应用程序使用多个类加载器,则一个类加载器加载的类可能不能被其他类加载器使用。为了更好地排除故障,了解它是很重要的类加载器在Java中是如何工作的
5.总结
虽然这两个异常都与类路径有关,但Java运行时无法在运行时找到类,注意它们的区别是很重要的。
Java运行时抛出类未发现例外当试图仅在运行时加载类时,在运行时提供了类名。在…情况下NoClassDefFoundError,类在编译时存在,但在运行时Java运行时无法在Java类路径中找到它。
与往常一样,可以找到所有示例的完整代码在GitHub。