ChatGPT解决这个技术问题 Extra ChatGPT

为什么我在 Java 中收到 NoClassDefFoundError?

我在运行 Java 应用程序时收到 NoClassDefFoundError。这通常是什么原因?

我相信如果您没有使用正确的语法运行您的 java 程序,它也会发生。例如,您必须使用完整的包名(即 my.package.myClass)从根 bin 文件夹中调用您的类。如果可以的话,我会更具体,但我不是一个 java 人。我只记得搞砸了几次。

O
OldPeculier

虽然这可能是由于编译时和运行时之间的类路径不匹配,但这不一定是真的。

在这种情况下,将两个或三个不同的例外直接放在我们的脑海中是很重要的:

java.lang.ClassNotFoundException 此异常表示在类路径中找不到该类。这表明我们正在尝试加载类定义,并且类路径中不存在该类。 java.lang.NoClassDefFoundError 该异常表示JVM在其内部类定义数据结构中查找类的定义,但没有找到。这与说它无法从类路径加载不同。通常这表明我们之前尝试从类路径加载一个类,但由于某种原因它失败了 - 现在我们试图再次使用该类(因此需要加载它,因为它上次失败了),但是我们'甚至不会尝试加载它,因为我们之前未能加载它(并且有理由怀疑我们会再次失败)。较早的失败可能是 ClassNotFoundException 或 ExceptionInInitializerError(指示静态初始化块中的失败)或任何数量的其他问题。关键是,NoClassDefFoundError 不一定是类路径问题。


感谢您提及 NoClassDefFoundError 的原因,这对我帮助很大!在我的情况下,之前抛出了 ExceptionInInitializerError,这就是我发现静态块中的错误的方式。
@Jared,当我得到 Error: Could not find or load main class 时,它将被归类为哪一类错误?
@Pops:使语言更加冗长以指定动词“try”的对象:)
@Vikram“找不到或加载主类”不是Java异常,它是由启动器(检查JAR和主清单属性)引起的。
当类具有引发错误或异常的静态初始化时,也会引发 ClassNotFoundException。他们可能应该为该事件选择一个不同的名称。
M
Mocky

当您的代码依赖于一个类文件并且它在编译时存在但在运行时找不到时会导致这种情况。寻找构建时间和运行时类路径的差异。


将源文件放在错误的命名空间/包下时发生此错误。我想我可以把它放在任何地方,编译器很高兴。事实证明,我应该更加努力地让运行时也开心。
当我的服务器在文件上传期间内存不足时,我曾经遇到过这个错误。每次我尝试上传时,我都会收到不同的错误。最终它告诉我我没有足够的堆空间。
这个答案不一定是真的,会误导很多人!请参阅下面 Jared 的更好答案。
@戴夫L。谢谢! Jared 得到 400 多票的回答远低于此!一个带有-4 up(down?)票的答案远高于它。 SO的答案排序逻辑有些可疑。
这对某人来说是一个远景,但我遇到了这个错误,因为有问题的类包含一个使用无效字符初始化的 SimpleDateFormat(我在中间有 T 而不是 'T')。
x
xli

这是说明 java.lang.NoClassDefFoundError 的代码。详细说明请参见Jared's answer

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();
    }

}

简单计算器.java

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

原因是在第一次尝试之后 jvm 已经知道它不会工作并第二次抛出不同的异常?
@ikamen 显然它在除以零之后存储了 SimpleCalculator 的不成功的类初始化?有人对此行为的官方文档有参考吗?
@PhilipRego 不确定“纯”NoClassDefFoundError 是什么意思。第一次调用 new SimpleCalculator() 时,您会得到一个 ExceptionInInitializerError,它由 ArithmeticException 引起。第二次调用 new SimpleCalculator() 时,您得到的 NoClassDefFoundError 与任何其他错误一样纯。关键是您可能会因为 SimpleCalculator.class 在运行时不在类路径上之外的原因而获得 NoClassDefFoundError。
A
Aftab

Java中的NoClassDefFoundError

定义:

Java 虚拟机无法在运行时找到在编译时可用的特定类。如果一个类在编译时存在,但在运行时在 java 类路径中不可用。

https://i.stack.imgur.com/bDVNo.gif

例子:

该类不在 Classpath 中,没有确切的方法可以知道它,但很多时候你可以看看打印 System.getproperty("java.classpath") ,它会从那里打印你至少可以得到的类路径您的实际运行时类路径的想法。 NoClassDefFoundError 的一个简单示例是类属于缺少的 JAR 文件或 JAR 未添加到类路径中,或者有时 jar 的名称已被某些人更改,例如我的一位同事已将 tibco.jar 更改为 tibco_v3.jar 并且程序是java.lang.NoClassDefFoundError 失败,我想知道出了什么问题。只需尝试使用您认为可以工作的类路径显式运行 -classpath 选项,如果它正在工作,那么这是一个肯定的简短信号,表明有人正在覆盖 java 类路径。 JAR 文件的权限问题也可能导致 Java 中的 NoClassDefFoundError。 XML 配置上的错字也可能导致 Java 中的 NoClassDefFoundError。当您在包中定义的编译类在加载时不存在于同一个包中时,就像在 JApplet 的情况下一样,它将在 Java 中抛出 NoClassDefFoundError。

可能的解决方案:

该类在 Java 类路径中不可用。如果您在 J2EE 环境中工作,多个 Classloader 之间的 Class 的可见性也会导致 java.lang.NoClassDefFoundError,请参阅示例和场景部分进行详细讨论。检查日志文件中的 java.lang.ExceptionInInitializerError。由于静态初始化失败导致的 NoClassDefFoundError 很常见。因为 NoClassDefFoundError 是 java.lang.LinkageError 的子类,所以如果其中一个依赖项(如本机库)可能不可用,它也会出现。任何启动脚本都会覆盖 Classpath 环境变量。您可能正在使用 jar 命令运行程序,并且清单文件的 ClassPath 属性中未定义类。

资源:

3 ways to solve NoClassDefFoundError

java.lang.NoClassDefFoundError Problem patterns


很好的答案。我想我已经尝试了你建议的一切,但仍然有这个问题。由于 jar 与 spring 一起使用,我可以排除其中的一些,但 java.sql 似乎不喜欢(在我的情况下是 Hana 的 sap db 驱动程序)。
它实际上称为 System.getproperty("java.class.path")
问题仍未解决,但它是非常有用的信息。
s
shsteimer

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

set classpath=%classpath%;axis.jar

我能够通过使用以下方法获取正确的版本:

set classpath=axis.jar;%classpath%;

有同样的问题。结果我用Java7编译了war文件,但我的Tomcat安装使用的是Java6。我不得不更新我的环境变量
如果发生这种情况,那么我会说 Java 一团糟。 +2 如果这是真的。尚无法验证这一点。如果找到 true 将再次做+1(在评论中)
R
Ram Patra

这是我目前发现的 best solution

假设我们有一个名为 org.mypackage 的包,其中包含以下类:

HelloWorld(主类)

支持类

实用程序类

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

https://i.stack.imgur.com/XOzAE.png

https://i.stack.imgur.com/cM8gu.png


C
Charlie

您可能会看到大量 NoClassDefFoundErrors 的一个有趣案例是:

在类 Example 的静态块中抛出 RuntimeException 拦截它(或者如果它只是在测试用例中抛出无关紧要)尝试创建此类 Example 的实例

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 时,这一点尤其重要。

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


这在现实生活中是非常有用的建议。我刚刚遇到了与类属性初始值设定项相同的情况。您只有一次机会在日志中看到实际问题。加载类(或无论如何尝试)后,您需要重新启动所有内容。
P
Peter Mortensen

我将 Spring FrameworkMaven 一起使用,并在我的项目中解决了这个错误。

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

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

@xli 的回答让我深入了解了我的代码中可能存在的问题。


我在编写 Servlet 时也发生了同样的事情(NoClassDefFoundError 实际上是由 ExceptionInInitalizerError 引起的,而 ExceptionInInitalizerError 是由 DateTimeParseException 引起的)。这有点误导,不是吗?我知道他们可能有他们这样做的理由,但如果至少有一个小提示,那就太好了,即 NoClassDefFoundError 是另一个异常的结果,无需推断它。再次抛出 ExceptionInInitializerError 会更清楚。有时两者之间的联系可能并不那么明显。
c
codeDr

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

使用“java -javaagent:tracer.jar [YOUR java ARGS]”运行程序

它生成显示加载的类的输出,以及加载该类的加载器环境。跟踪类无法解析的原因非常有帮助。

// 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;
            }
        });
    }
}

A
Aram Paronikyan

下面的技术帮助了我很多次:

System.out.println(TheNoDefFoundClass.class.getProtectionDomain().getCodeSource().getLocation());

其中 TheNoDefFoundClass 是由于偏爱程序使用的同一库的旧版本而可能“丢失”的类。这种情况最常发生在这样的情况下,当客户端软件被部署到一个占主导地位的容器中时,它配备了自己的类加载器和大量最流行的库的古老版本。


P
Peter Mortensen

如果您有生成代码(EMF 等),则可能有太多静态初始化程序会占用所有堆栈空间。

请参阅 Stack 溢出问题 How to increase the Java stack size?


“电磁场”?你是说MEF吗?
没有。 EMf 作为 Eclipse 建模框架。在汽车中,我们在运行生成的代码时可能会遇到这个错误。
2
2240

ClassNotFoundException 与 NoClassDefFoundError

[ClassLoader]

静态与动态类加载

Static(Implicit) class loading - 引用、实例化或继承的结果。

MyClass myClass = new MyClass();

Dynamic(Explicit) class loading 是 Class.forName()、loadClass()、findSystemClass() 的结果

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

每个类都有一个使用 loadClass(String name);ClassLoader,这就是为什么

explicit class loader uses implicit class loader

NoClassDefFoundErrorexplicit class loader 的一部分。 Error 保证在编译期间该类被呈现,但现在(在运行时)它不存在。

ClassNotFoundExceptionimplicit class loader 的一部分。 Exception 在另外可以使用的场景中具有弹性 - 例如反射。


m
manuelvigarcia

同一项目的两个不同的结帐副本

就我而言,问题在于 Eclipse 无法区分同一项目的两个不同副本。我有一个锁定在主干上(SVN 版本控制),另一个在一个分支中工作。我在工作副本中尝试了一个更改作为 JUnit 测试用例,其中包括将私有内部类提取为自己的公共类,当它工作时,我打开项目的另一个副本以查看其他的需要更改的部分代码。在某些时候,NoClassDefFoundError 突然出现,抱怨私有内部类不存在;双击堆栈跟踪将我带到错误项目副本中的源文件。

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


M
Michael

我通过禁用所有模块的 preDexLibraries 解决了我的问题:

dexOptions {
        preDexLibraries false
        ...

A
Alan Ackart

当我将另一个模块的 Maven 依赖项添加到我的项目时出现此错误,该问题最终通过将 -Xss2m 添加到我的程序的 JVM 选项来解决(自 JDK5.0 以来默认为 1 兆字节)。相信程序没有足够的堆栈来加载类。


ᴠɪɴᴄᴇɴᴛ

static 初始化程序尝试加载在运行时不可用的资源包(例如受影响的类尝试从 META-INF 目录加载的属性文件,但不在那里。如果您没有捕获 NoClassDefFoundError,有时您将无法看到完整的堆栈跟踪;为了克服这个问题,您可以暂时对 Throwable 使用 catch 子句:

try {
    // Statement(s) that cause(s) the affected class to be loaded
} catch (Throwable t) {
    Logger.getLogger("<logger-name>").info("Loading my class went wrong", t);
}

这是不正确的。缺少的资源不会给你这个错误。只有缺课时,您才会得到它。
@StephenC 也许我应该更多地强调那部分,但我写了 for example a properties file that the affected class tries to load from the META-INF directory。这实际上发生在我身上,我能够通过添加缺少的属性文件来解决 NoClassDefFoundError。我添加了这个答案正是因为在上述情况下不会出现这个错误。
您在解释中遗漏了一些非常重要的内容,因为缺少资源文件可能触发该异常的唯一方法是您尝试在 static 初始化中加载资源文件...这触发了未经检查的异常并导致类初始化失败。从静态初始化传播的任何未经检查的异常都会这样做。
如果我错了(即这不是由于 static 初始化失败),我将有兴趣查看演示该行为的实际示例(即 MCVE)。
@StephenC你是绝对正确的,不过:(我查看了我遇到这个问题的案例,它确实涉及一个试图加载资源包的静态初始化程序。我将增加/更正我对原因的描述。感谢您指出这一点出去。
p
priyanka_rao

尝试在 Tomcat/JBOSS 服务器上部署应用程序时遇到 NoClassDefFoundError。我使用不同的依赖项来解决问题,但不断收到相同的错误。将所有 javax.* 依赖项标记为 pom.xml 中提供的,并且 war 实际上没有依赖项。问题还是不断出现。

最后意识到 src/main/webapps/WEB-INF/classes 有 classes 文件夹,该文件夹被复制到我的战争中,所以不是编译的类,而是复制这些类,因此没有依赖项更改解决问题。

因此,如果要复制任何以前编译的数据,请小心,删除类文件夹和重新编译后,它起作用了!..


S
ST7

如果有人因为 java.lang.NoClassDefFoundError: org/apache/log4j/Logger 错误而来到这里,在我的情况下,它是因为我使用了 log4j 2(但我没有添加它附带的所有文件)而产生的,并且一些依赖库使用了 log4j 1。解决方案是添加 Log4j 1.x 桥:log4j 2 附带的 jar log4j-1.2-api-<version>.jar。更多信息请参见 log4j 2 migration


B
Brent Bradburn

此错误可能是由未经检查的 Java 版本要求引起的。

在我的例子中,通过使用 SDKMAN! 从 Java 9 切换到 Java 8,我能够在构建一个备受瞩目的开源项目时解决此错误。

sdk list java
sdk install java 8u152-zulu
sdk use java 8u152-zulu

然后如下所述进行全新安装。

当使用 Maven 作为你的构建工具时,在禁用测试的情况下进行干净的“安装”构建有时会很有帮助——而且通常是令人满意的。

mvn clean install -DskipTests

现在一切都已构建和安装,您可以继续运行测试。

mvn test

S
Steve Stilson

当我没有在项目的 Java 构建路径的“订购和导出”选项卡上导出类时,出现 NoClassDefFound 错误。确保在添加到项目构建路径的任何依赖项的“订购和导出”选项卡中打勾。请参阅Eclipse warning: XXXXXXXXXXX.jar will not be exported or published. Runtime ClassNotFoundExceptions may result


o
off99555

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


B
Ben Waters

就我而言,由于 JDK 版本不匹配,我收到此错误。当我尝试从 Intelij 运行该应用程序时,它无法正常工作,但随后从命令行运行它就可以了。这是因为 Intelij 试图使用已设置的 Java 11 JDK 运行它,但在命令行上它使用 Java 8 JDK 运行。在“文件”>“项目结构”>“项目设置”>“项目 SDK”下切换该设置后,它对我有用。


b
bdskfsdk321dsad3

每个人都在这里谈论一些 Java 配置内容、JVM 问题等,在我的情况下,错误与这些主题完全无关,并且有一个非常简单且易于解决的原因:我的 Controller 的端点有一个错误的注释( Spring Boot 应用程序)。


p
pixel

我在使用 Liberty 服务器的 JavaEE 中遇到了一个有趣的问题,即 NoClassDefFoundError。我正在使用 IMS 资源适配器,而我的 server.xml 已经有 imsudbJXA.rar 的资源适配器。当我为 imsudbXA.rar 添加新适配器时,我会开始为 DLIException、IMSConnectionSpec 或 SQLInteractionSpec 的实例对象收到此错误。我不知道为什么,但我通过只使用 imsudbXA.rar 为我的工作创建新的 server.xml 来解决它。我确信在 server.xml 中使用多个资源适配器很好,我只是没有时间研究。


l
logbasex

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

在 Java SE 11 中,您可以选择直接启动单个源代码文件,而无需中间编译。只是为了您的方便,让像您这样的新手不必运行 javac + java (当然,让他们感到困惑为什么会这样)。


T
Thomas McSwain

我有这个错误,但无法根据这个线程找出解决方案,但我自己解决了。

对于我的问题,我正在编译这段代码:

package valentines;

import java.math.BigInteger;
import java.util.ArrayList;

public class StudentSolver {
    public static ArrayList<Boolean> solve(ArrayList<ArrayList<BigInteger>> problems) {
        //DOING WORK HERE
        
    }
    public static void main(String[] args){
        //TESTING SOLVE FUNCTION
    }
    
}

然后我在类似于 /ProjectName/valentines 的文件夹结构中编译此代码编译它工作正常但尝试执行:java StudentSolver

我得到了 NoClassDefError。

为了解决这个问题,我简单地删除了:package valentines;

我不太精通java包等,但这就是我修复错误的方式,如果其他人已经回答了这个问题,我很抱歉,但我无法将其解释为我的问题。


P
Pekmezli Dürüm

Java 在运行时找不到类 A。 A 类位于来自不同工作区的 Maven 项目 ArtClient 中。所以我将 ArtClient 导入到我的 Eclipse 项目中。我的两个项目使用 ArtClient 作为依赖项。我将库引用更改为这些项目的引用(构建路径-> 配置构建路径)。

问题消失了。


P
Peter Mortensen

我也遇到了同样的问题,而且我存货了好几个小时。

我找到了解决方案。就我而言,因此定义了静态方法。 JVM 不能创建该类的另一个对象。

例如,

private static HttpHost proxy = new HttpHost(proxyHost, Integer.valueOf(proxyPort), "http");

P
Peter Mortensen

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

我的解决方案是:重新启动 Eclipse。从那以后我再也没有看到这条消息:-)


投票最多的答案解释了这一点,当你第一次编译时,文件在那里,然后你删除了一些文件,这些类被删除了,所以在运行时,你得到了 ClassNotFound,然后你把它们带回来,但 Eclipse 仍然没有请注意,生成的类仍然丢失,但是在您重新启动 Eclipse 后,工作区被刷新并且类再次可用,但通常这不是解决方案或解决方法,解决方案是查找运行时中缺少哪个类/jar类路径。
P
Peter Mortensen

确保这在 module:appmodule:lib 中匹配:

android {
    compileSdkVersion 23
    buildToolsVersion '22.0.1'
    packagingOptions {
    }

    defaultConfig {
        minSdkVersion 17
        targetSdkVersion 23
        versionCode 11
        versionName "2.1"
    }

您的解决方案与这个常见问题有何关联?
示例配置不平衡(三个 {s 和两个 })。你能修好它吗?