为什么我在Java中获得NoClassDefFoundError?

问题描述 投票:468回答:21

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

java noclassdeffounderror
21个回答
237
投票

这是因为当您的代码依赖于类文件并且它在编译时出现但在运行时未找到时。查找构建时和运行时类路径的差异。


3
投票

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

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


2
投票

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

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

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


1
投票

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

dexOptions {
        preDexLibraries false
        ...

1
投票

当静态初始化程序尝试加载运行时不可用的资源包时,也会发生NoClassDefFoundError,例如受影响的类尝试从META-INF目录加载但不存在的属性文件。如果你没有抓住NoClassDefFoundError,有时你将无法看到完整的堆栈跟踪;为了克服这一点,你可以暂时使用catch条款为Throwable

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

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中。


0
投票

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

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

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


0
投票

此错误可能是由未经检查的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

0
投票

当我没有在项目的Java Build Path中的“Order and Export”选项卡上导出类时,我得到了NoClassDefFound错误。确保在添加到项目构建路径的任何依赖项的“Order and Export”选项卡中添加一个复选标记。见Eclipse warning: XXXXXXXXXXX.jar will not be exported or published. Runtime ClassNotFoundExceptions may result


-1
投票

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

而问题消失了。


-1
投票

我有同样的问题,我有很多小时的存量。

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

例如,

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

732
投票

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

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

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

-6
投票

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

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


-7
投票

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

android {
    compileSdkVersion 23
    buildToolsVersion '22.0.1'
    packagingOptions {
    }

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

108
投票

这是用来说明java.lang.NoClassDefFoundError的代码。有关详细说明,请参阅Jared's answer

no class def found error demo.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();
    }

}

simple calculator.Java

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

31
投票

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

set classpath=%classpath%;axis.jar

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

set classpath=axis.jar;%classpath%;

30
投票

NoClassDefFoundError在Java中

定义:

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

enter image description here

例子:

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

可能的解决方案:

  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属性中定义类。

资源:

3 ways to solve NoClassDefFoundError

java.lang.NoClassDefFoundError Problem patterns


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
投票

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

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

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

@ xli的回答让我深入了解了我的代码可能出错的地方。


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

4
投票

如果你在UNIT TESTS中看到NoClassDefFoundErrors,请特别阅读本文...


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

  1. throwRuntimeExceptionstatic街区的Example
  2. 拦截它(或者如果它只是在测试用例中抛出并不重要)
  3. 尝试创建此类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将与静态区块ExceptionInInitializerErrorRuntimeException一起被抛出。


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

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

© www.soinside.com 2019 - 2024. All rights reserved.