ClassLoader.loadClass()令人惊讶地抛出NoClassDefFoundError而不是ClassNotFoundException

时间:2017-04-03 04:55:48

标签: java classloader

我有一个名为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]

它不重复,因为我正在寻找名称更改方案的不同例外,请再次检查

2 个答案:

答案 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文件中而不是依赖于文件系统,则会获得系统独立一致的行为。