当您的代码运行“new Y()”并且找不到 Y 类时,会发生 NoClassDefFoundError (NCDFE)。
可能只是像其他评论所暗示的那样,您的类加载器中缺少 Y,但可能是 Y 类没有签名或签名无效,或者 Y 是由您的代码不可见的不同类加载器加载的,甚至 Y 依赖于 Z ,由于上述任何原因而无法加载。
如果发生这种情况,那么 JVM 将记住加载 X (NCDFE) 的结果,并且每次您请求 Y 时它都会简单地抛出一个新的 NCDFE,而不会告诉您原因:
类{
静态类 b {}
公共静态无效主要(字符串参数[]){
System.out.println("第一次尝试 new b():");
试试 {新 b(); } catch(Throwable t) {t.printStackTrace();}
System.out.println("\n第二次尝试 new b():");
试试 {新 b(); } catch(Throwable t) {t.printStackTrace();}
}
}
将其保存为 a.java 某处
该代码只是尝试两次实例化一个新的“b”类,除此之外,它没有任何错误,也没有做任何事情。
用 编译代码javac a.java
,然后通过调用运行 a java -cp . a
——它应该只打印出两行文本,并且应该可以正常运行而没有错误。
然后删除“a$b.class”文件(或用垃圾填充它,或将a.class 复制到它上面)以模拟丢失或损坏的类。这是发生的事情:
第一次尝试新 b():
java.lang.NoClassDefFoundError: a$b
在 a.main(a.java:5)
引起:java.lang.ClassNotFoundException:a$b
在 java.net.URLClassLoader$1.run(URLClassLoader.java:200)
在 java.security.AccessController.doPrivileged(本机方法)
在 java.net.URLClassLoader.findClass(URLClassLoader.java:188)
在 java.lang.ClassLoader.loadClass(ClassLoader.java:307)
在 sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
在 java.lang.ClassLoader.loadClass(ClassLoader.java:252)
在 java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320)
... 1 更多
第二次尝试新 b():
java.lang.NoClassDefFoundError: a$b
在 a.main(a.java:7)
第一次调用会导致 ClassNotFoundException(由类加载器在找不到类时抛出),它必须包含在未经检查的 NoClassDefFoundError 中,因为有问题的代码 ( new b()
) 应该可以正常工作。
第二次尝试当然也会失败,但正如您所见,包装的异常不再存在,因为 ClassLoader 似乎记住了失败的类加载器。您只看到 NCDFE,完全不知道到底发生了什么。
因此,如果您看到没有根本原因的 NCDFE,您需要查看是否可以追溯到第一次加载类以找到错误原因。