为什么我在Java中获得NoClassDefFoundError?

时间:2008-08-29 14:59:31

标签: java noclassdeffounderror

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

30 个答案:

答案 0 :(得分:722)

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

在这种情况下,重要的是要保持两到三个不同的例外:

  1. java.lang.ClassNotFoundException 此异常表示在类路径中找不到该类。这表明我们正在尝试加载类定义,并且该类在类路径中不存在。

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

答案 1 :(得分:235)

当您的代码所依赖的类文件存在于编译时但在运行时未找到时,会导致这种情况。查找构建时和运行时类路径的差异。

答案 2 :(得分:103)

以下是说明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();
    }

}

SimpleCalculator.java

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

答案 3 :(得分:31)

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

set classpath=%classpath%;axis.jar

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

set classpath=axis.jar;%classpath%;

答案 4 :(得分:29)

Java中的NoClassDefFoundError

定义:

  1. Java虚拟机无法在运行时找到编译时可用的特定类。

  2. 如果某个类在编译期间存在但在运行时期间在java类路径中不可用。

  3. enter image description here

    <强>示例:

    1. 该类不在Classpath中,没有确定的知道它的方法,但很多时候你可以看一下打印System.getproperty(&#34; java.classpath&#34;)它会打印出来从那里你可以至少知道你的实际运行时类路径。
    2. NoClassDefFoundError的一个简单示例是类属于缺少的JAR文件,或者JAR没有被添加到类路径中,或者有时jar的名称已被某人更改,就像在我的情况下我的一位同事改变了tibco .jar进入tibco_v3.jar并且程序失败了java.lang.NoClassDefFoundError,我想知道什么是错的。

    3. 尝试使用显式的-classpath选项运行您认为可行的类路径,如果它正常工作,那么确定有人覆盖java类路径的短信号。

    4. JAR文件的权限问题也可能导致Java中的NoClassDefFoundError。
    5. 错误配置上的错误也可能导致Java中的NoClassDefFoundError。
    6. 当你在包中定义的编译类在加载时不会出现在同一个包中,就像在JApplet中一样,它将在Java中抛出NoClassDefFoundError。
    7. 可能的解决方案:

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

        3 ways to solve NoClassDefFoundError

        java.lang.NoClassDefFoundError Problem patterns

答案 5 :(得分:7)

这是我到目前为止发现的best solution

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

  • HelloWorld(主要课程)
  • SupportClass
  • UtilClass

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

文件结构如下所示: enter image description here

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

答案 6 :(得分:6)

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

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

Spring没有给我一个关于运行时失败的哪一行的完整堆栈跟踪。 它简单地说NoClassDefFoundError。但是当我将它作为本机Java应用程序执行(将其从MVC中取出)时,它给出了ExceptionInInitializerError这是真正的原因,这就是我如何跟踪错误。

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

答案 7 :(得分:5)

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

使用'java -javaagent:tracer.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;
            }
        });
    }
}

答案 8 :(得分:4)

尤其在您在UNIT TESTS中看到NoClassDefFoundErrors时,请仔细阅读...


一种有趣的情况是,您可能会遇到许多NoClassDefFoundErrors

    在课程throw的{​​{1}}块中的
  1. RuntimeExceptionstatic
  2. 拦截它(或者就像在测试用例中抛出它一样没关系)
  3. 尝试创建此类Example的实例

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一起从静态块ExceptionInInitializerError中抛出。


当您在单元测试中看到RuntimeException时,这尤其重要。

您可以在测试之间“共享” NoClassDefFoundErrors块执行,但是初始的static仅在一个测试用例中。第一个使用有问题的ExceptionInInitializerError类。使用Example类的其他测试用例只会抛出Example

答案 9 :(得分:3)

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

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

答案 10 :(得分:2)

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

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

其中TheNoDefFoundClass可能是&#34;丢失&#34;由于您偏爱程序使用的同一个库的旧版本。最常见的情况是,当客户端软件被部署到占主导地位的容器中时,它拥有自己的类加载器和大量最流行的库的古老版本。

答案 11 :(得分:1)

我通过禁用所有模块的preDexLibraries修复了我的问题:

dexOptions {
        preDexLibraries false
        ...

答案 12 :(得分:1)

静态初始化程序尝试加载运行时不可用的资源束时,例如也会出现

NoClassDefFoundError,例如,受影响的类尝试从{ {1}}目录,但不存在。如果您没有抓住META-INF,有时您将看不到完整的堆栈跟踪信息;为了克服这个问题,您可以为NoClassDefFoundError临时使用catch子句:

Throwable

答案 13 :(得分:0)

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

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

explicit class loader uses implicit class loader

NoClassDefFoundErrorexplicit class loader 的一部分。 Error 保证在编译过程中出现了这个类,但现在 (在tun时间)它不存在

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

答案 14 :(得分:0)

我遇到了这个错误,但无法找出基于该线程的解决方案,但自己解决了。

对于我的问题,我正在编译以下代码:

go mod vendor

然后我在类似于/ ProjectName / valentines的文件夹结构中编译此代码 编译正常,但尝试执行: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 } }

我收到了NoClassDefError。

要解决此问题,我只删除了:java StudentSolver

我不太精通Java程序包,但是我如何解决错误,如果其他人已经回答了它,但我无法解释我的问题,我对此感到抱歉。

答案 15 :(得分:0)

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

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

答案 16 :(得分:0)

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

答案 17 :(得分:0)

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

答案 18 :(得分:0)

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

答案 19 :(得分:0)

我在尝试在 Tomcat/JBOSS 服务器上部署应用程序时遇到 NoClassDefFoundError。我使用不同的依赖项来解决这个问题,但一直遇到同样的错误。将所有 javax.* 依赖项标记为 pom.xml 中提供的,并且 war 字面上没有依赖项。问题仍然不断出现。

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

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

答案 20 :(得分:0)

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

答案 21 :(得分:0)

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

答案 22 :(得分:0)

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

答案 23 :(得分:0)

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

在我的情况下,通过使用SDKMAN!从Java 9切换到Java 8,我能够在构建高知名度的开源项目时解决此错误。

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

然后按照以下说明进行全新安装。

使用 Maven 作为构建工具时,在禁用测试的情况下执行 clean 'install'build 有时会很有帮助 - 通常也很有意义/强>

mvn clean install -DskipTests

现在已经构建并安装了所有,您可以继续运行测试。

mvn test

答案 24 :(得分:0)

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

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

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

答案 25 :(得分:0)

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

答案 26 :(得分:-1)

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

问题消失了。

答案 27 :(得分:-1)

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

我找到了解决方案。在我的例子中,由于这个原因定义了静态方法。 JVM无法创建该类的另一个对象。

例如,

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

答案 28 :(得分:-6)

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

我的解决方案是:重启Eclipse。从那时起,我再没有看到这个消息: - )

答案 29 :(得分:-7)

确保此匹配符合module:appmodule:lib

android {
    compileSdkVersion 23
    buildToolsVersion '22.0.1'
    packagingOptions {
    }

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