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


当前回答

更新[https://www.infoq.com/articles/single-file-execution-java11/]:

在Java SE 11中,可以选择启动单个源代码文件 直接,不需要中间编译。为了方便大家, 所以像你这样的新手不需要运行javac + Java(当然, 让他们感到困惑)。

其他回答

更新[https://www.infoq.com/articles/single-file-execution-java11/]:

在Java SE 11中,可以选择启动单个源代码文件 直接,不需要中间编译。为了方便大家, 所以像你这样的新手不需要运行javac + Java(当然, 让他们感到困惑)。

当运行时类装入器装入的类不能访问已经由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;
            }
        });
    }
}

这是迄今为止我找到的最好的解决办法。

假设我们有一个名为org的包。Mypackage包含的类:

HelloWorld(主类) SupportClass UtilClass

定义这个包的文件物理存储在目录D:\myprogram (Windows)或/home/user/myprogram (Linux)下。

文件结构如下所示:

当调用Java时,我们指定要运行的应用程序的名称:org.mypackage.HelloWorld。但是,我们还必须告诉Java在哪里查找定义包的文件和目录。所以要启动程序,我们必须使用下面的命令:

在我的情况下,由于JDK版本不匹配,我得到了这个错误。当我试图从Intelij运行应用程序时,它不工作,但从命令行运行它就工作了。这是因为Intelij试图用Java 11 JDK运行它,但在命令行上,它是用Java 8 JDK运行的。在文件>项目结构>项目设置>项目SDK下切换设置后,它为我工作了。

我在项目中使用Spring Framework和Maven解决了这个错误。

类中存在运行时错误。我将一个属性读取为整数,但是当它从属性文件读取值时,它的值是double。

Spring没有提供运行时在哪一行上失败的完整堆栈跟踪。 它只是说NoClassDefFoundError。但是当我作为一个原生Java应用程序执行它时(将它从MVC中取出),它给出了ExceptionInInitializerError,这是真正的原因,也是我跟踪错误的方式。

@xli的回答让我洞察到我的代码中可能存在的错误。