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


当前回答

当我没有在项目的Java Build Path中的“Order and export”选项卡上导出一个类时,我得到了NoClassDefFound错误。确保在添加到项目构建路径的任何依赖项的“Order and Export”选项卡中添加一个复选标记。请参见Eclipse警告:XXXXXXXXXXX.jar将不会被导出或发布。可能会导致运行时ClassNotFoundExceptions。

其他回答

下面是演示java.lang.NoClassDefFoundError的代码。具体的解释请看Jared的回答。

NoClassDefFoundErrorDemo.java

public class NoClassDefFoundErrorDemo {
    public static void main(String[] args) {
        try {
            // The following line would throw ExceptionInInitializerError
            SimpleCalculator calculator1 = new SimpleCalculator();
        } catch (Throwable t) {
            System.out.println(t);
        }
        // The following line would cause NoClassDefFoundError
        SimpleCalculator calculator2 = new SimpleCalculator();
    }

}

SimpleCalculator.java

public class SimpleCalculator {
    static int undefined = 1 / 0;
}

同一项目的两个不同的签出副本

In my case, the problem was Eclipse's inability to differentiate between two different copies of the same project. I have one locked on trunk (SVN version control) and the other one working in one branch at a time. I tried out one change in the working copy as a JUnit test case, which included extracting a private inner class to be a public class on its own and while it was working, I open the other copy of the project to look around at some other part of the code that needed changes. At some point, the NoClassDefFoundError popped up complaining that the private inner class was not there; double-clicking in the stack trace brought me to the source file in the wrong project copy.

关闭项目的主干副本并再次运行测试用例可以解决这个问题。

当运行时类装入器装入的类不能访问已经由java rootloader装入的类时,我得到NoClassFoundError。因为不同的类装入器在不同的安全域中(根据java), jvm不允许已经由rootloader装入的类在运行时装入器地址空间中被解析。

使用'java -javaagent:trace .jar[你的java ARGS]'运行程序

它产生显示已加载类的输出,以及加载该类的加载器env。追踪类为什么不能解析是非常有用的。

// ClassLoaderTracer.java
// From: https://blogs.oracle.com/sundararajan/entry/tracing_class_loading_1_5

import java.lang.instrument.*;
import java.security.*;

// manifest.mf
// Premain-Class: ClassLoadTracer

// jar -cvfm tracer.jar manifest.mf ClassLoaderTracer.class

// java -javaagent:tracer.jar  [...]

public class ClassLoadTracer 
{
    public static void premain(String agentArgs, Instrumentation inst) 
    {
        final java.io.PrintStream out = System.out;
        inst.addTransformer(new ClassFileTransformer() {
            public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {

                String pd = (null == protectionDomain) ? "null" : protectionDomain.getCodeSource().toString();
                out.println(className + " loaded by " + loader + " at " + new java.util.Date() + " in " + pd);

                // dump stack trace of the thread loading class 
                Thread.dumpStack();

                // we just want the original .class bytes to be loaded!
                // we are not instrumenting it...
                return null;
            }
        });
    }
}

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

这也可能是因为您从具有特定包名的IDE复制了代码文件,并且希望尝试使用终端运行它。您必须首先从代码中删除包名。 这种事发生在我身上。