我有一个名为MyClass
的班级,所以当我打电话时
classloader.loadClass("myclass")
会引发NoClassDefFoundError
而不是ClassNotFoundException
。
注意 - 我已将大写字母改为小写字母
当我使用完全不同的字符串" ABC"我按预期得到ClassNotFoundException
。
请在下面找到代码段。
public class Test {
public static void main(String[] args) {
// normal conditions
try {
Test.class.getClassLoader().loadClass("MyClass");
System.out.println(" Successfully loaded an existing class ");
} catch (ClassNotFoundException notExpected) {
}
// expected
try {
Test.class.getClassLoader().loadClass("ABC");
} catch (ClassNotFoundException expected) {
System.out.println("Expected");
}
try {
Test.class.getClassLoader().loadClass("myclass");
} catch (ClassNotFoundException expected) {
System.out.println("Expected but not coming");
}
}
}
//
// sample class used for the above in separate file
//
public class MyClass
{
}
输出:
Successfully loaded an existing class
Expected
Exception in thread "main" java.lang.NoClassDefFoundError: myclass (wrong name: MyClass)
[![Java 8 Machine上的输出] [1]] [1]
它不重复,因为我正在寻找名称更改方案的不同例外,请再次检查
答案 0 :(得分:0)
我已按原样复制您的程序并在我的计算机上运行(Windows 10上的Java jdk1.8.0_121)。它产生的输出是:
Expected
Expected but not coming
所以可能你的测试的某些部分还没有被删除,或者你在一个jvm上运行,这个jvm有一个已经在最新版本中修复过的bug(不太可能是这样但是可能性仍然存在)存在)。
关于这些例外,有一篇非常好的文章:available here
因此,当类在编译期间可用时,抛出NoClassDefFoundError
(它的错误,而不仅仅是异常,顺便说一下!),但后来在运行时从类路径中删除了。 JVM真正依赖于这个类,但它并不存在,所以JVM被迫抛出这样的错误。
请你重新编译你的项目,并确保你没有真正拥有" myclass.java"在编译期间作为磁盘上的文件?
我要检查的另一个选项是将JVM升级到最新版本并再次尝试。
答案 1 :(得分:0)
ClassNotFoundException
ClassLoader
用于在loadClass
尝试时立即报告缺席课程与LinkageError
的子类型之间存在根本区别在找到类时抛出,但是违反了结构约束或者无法解析依赖关系。
由于懒惰的解析/验证,这些LinkageError
(包括NoClassDefFoundError
)的子类型可能会在很晚的时候被抛出。
因此,在您的情况下,已加载类文件,显然是因为您的操作系统或文件系统不区分大小写,但NoClassDefFoundError
由于名称不匹配而被defineClass
抛出(请注意,此方法将预期名称作为参数)。
如this answer中所述,如果将类文件存储到jar
文件中而不是依赖于文件系统,则会获得系统独立一致的行为。