当我运行Java应用程序时,我得到了一个NoClassDefFoundError。造成这种情况的典型原因是什么?


当前回答

Java ClassNotFoundException vs NoClassDefFoundError

黑ClassLoader铝

静态与动态类加载

静态(隐式)类加载——引用、实例化或继承的结果。

MyClass myClass = new MyClass();

动态(显式)类加载是class . forname (), loadClass(), findSystemClass()的结果

MyClass myClass = (MyClass) Class.forName("MyClass").newInstance();

每个类都有一个ClassLoader,它使用loadClass(字符串名);这就是为什么

explicit class loader uses implicit class loader

NoClassDefFoundError是显式类装入器的一部分。Error是为了保证在编译期间出现这个类,但现在(在运行时)它不存在。

ClassNotFoundException是隐式类装入器的一部分。Exception对于可以额外使用的场景(例如反射)具有弹性。

其他回答

我发现,当使用运行时发现的不兼容的类版本编译代码时,有时会得到NoClassDefFound错误。我记得的具体实例是apache axis库。在我的运行时类路径上实际上有2个版本,它正在挑选过时和不兼容的版本,而不是正确的版本,导致NoClassDefFound错误。这是在一个命令行应用程序中,我正在使用类似的命令。

set classpath=%classpath%;axis.jar

我能够让它拿起正确的版本使用:

set classpath=axis.jar;%classpath%;

有一个有趣的例子,你可能会看到很多NoClassDefFoundErrors:

在类的静态块中抛出一个RuntimeException 拦截它(或者如果它在测试用例中抛出并不重要) 尝试创建该类的实例

static class Example {
    static {
        thisThrowsRuntimeException();
    }
}

static class OuterClazz {

    OuterClazz() {
        try {
            new Example();
        } catch (Throwable ignored) { //simulating catching RuntimeException from static block
            // DO NOT DO THIS IN PRODUCTION CODE, THIS IS JUST AN EXAMPLE in StackOverflow
        }

        new Example(); //this throws NoClassDefFoundError
    }
}

NoClassDefError将伴随来自静态块RuntimeException的ExceptionInInitializerError一起抛出。


当你在UNIT TESTS中看到NoClassDefFoundErrors时,这一点尤其重要。

在某种程度上,您在测试之间“共享”静态块执行,但初始的ExceptionInInitializerError将仅在一个测试用例中。第一个使用有问题的Example类。其他使用Example类的测试用例只会抛出NoClassDefFoundErrors。

如果有人因为java.lang.NoClassDefFoundError: org/apache/log4j/Logger错误来到这里,在我的例子中,它是因为我使用了log4j 2(但我没有添加它附带的所有文件),而一些依赖库使用了log4j 1。解决方案是添加Log4j 1。X桥:log4j-1.2-api-<version>.jar,随log4j 2而来。更多信息在log4j 2迁移中。

每个人都在这里谈论一些Java配置的东西,JVM的问题等,在我的情况下,错误与这些主题完全无关,有一个非常琐碎和容易解决的原因:我在我的控制器(Spring Boot应用程序)的端点有一个错误的注释。

我从SRC库中删除了两个文件后得到了这个消息,当我把它们带回来时,我一直看到这个错误消息。

我的解决方案是:重新启动Eclipse。从那以后我就再没见过这条消息了:-)