为什么java中会出现noclassdeffounderror?

ars1skjm  于 2021-08-25  发布在  Java
关注(0)|答案(17)|浏览(450)

我得到一份工作 NoClassDefFoundError 当我运行java应用程序时。典型的原因是什么?

unguejic

unguejic1#

此错误可能由未检查的java版本要求引起。
在我的例子中,通过使用sdkman!从java9切换到java8,我在构建一个引人注目的开源项目时解决了这个错误!。

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

然后按如下所述进行清洁安装。
当使用maven作为构建工具时,它有时是有用的——而且是常见的

kmpatx3s

kmpatx3s2#

NoClassDefFoundError 当静态初始值设定项尝试加载在运行时不可用的资源包(例如受影响的类尝试从 META-INF 目录,但不在那里。如果你没赶上 NoClassDefFoundError ,有时您将无法看到完整的堆栈跟踪;要克服这个问题,您可以暂时使用 catch 条款 Throwable :

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

wd2eg0qa3#

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

af7jpaap

af7jpaap4#

这是由于存在代码所依赖的类文件,并且该类文件在编译时存在,但在运行时找不到。查找构建时和运行时类路径中的差异。

czfnxgou

czfnxgou5#

虽然这可能是由于编译时和运行时之间的类路径不匹配造成的,但这不一定是真的。
在这种情况下,在我们的头脑中保持两个或三个不同的例外是很重要的: java.lang.ClassNotFoundException 此异常表示在类路径上找不到该类。这表明我们试图加载类定义,而类路径上不存在该类。 java.lang.NoClassDefFoundError 此异常表示jvm在其内部类定义数据结构中查找了类的定义,但没有找到它。这不同于说它不能从类路径加载。通常这表示我们以前试图从类路径加载一个类,但由于某种原因失败了-现在我们尝试再次使用该类(因此需要加载它,因为它上次失败了),但我们甚至不打算尝试加载它,因为我们之前加载它失败了(并且有理由怀疑我们会再次失败)。早期的故障可能是classnotfoundexception或ExceptionInInitializeError(指示静态初始化块中的故障)或任何数量的其他问题。关键是,noclassdeffounderror不一定是类路径问题。

pvcm50d1

pvcm50d16#

下面是要说明的代码 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;
}
tzxcd3kk

tzxcd3kk7#

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

示例:
该类不在类路径中,没有确切的方法知道它,但很多时候,您只需查看一下打印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环境中工作,那么类在多个类加载器之间的可见性也可能导致java.lang.noclassdeffounderror,请参阅示例和场景部分以获取详细讨论。
检查日志文件中的java.lang.exceptionininitializererror。由于静态初始化失败而导致的noclassdeffounderror非常常见。
因为noclassdeffounderror是java.lang.linkageerror的一个子类,所以如果像本机库这样的依赖项之一不可用,它也可能出现。
任何启动脚本都将覆盖classpath环境变量。
您可能正在使用jar命令运行程序,而在清单文件的classpath属性中未定义类。
资源:
解决noclassdeffounderror的3种方法
java.lang.noclassdeffounderror问题模式

x8diyxa7

x8diyxa78#

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

set classpath=%classpath%;axis.jar

我能够通过使用以下工具使其获得正确的版本:

set classpath=axis.jar;%classpath%;
1bqhqjot

1bqhqjot9#

这是迄今为止我找到的最好的解决方案。
假设我们有一个叫做 org.mypackage 包含以下类别:
helloworld(主类)
支持类
实用类
定义此包的文件物理存储在目录下 D:\myprogram (在Windows上)或 /home/user/myprogram (在linux上)。
文件结构如下所示:

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

jucafojl

jucafojl10#

我在maven中使用spring框架,并在我的项目中解决了这个错误。
类中存在运行时错误。我将属性读取为整数,但当它从属性文件中读取值时,其值是双倍的。
spring没有给出运行时失败的行的完整堆栈跟踪。它只是说 NoClassDefFoundError . 但当我将其作为本地java应用程序执行时(将其从mvc中删除),它给出了 ExceptionInInitializerError 这是真正的原因,也是我追踪错误的方式。
@xli的回答让我洞察了代码中可能存在的错误。

uttx8gqw

uttx8gqw11#

一个有趣的案例,你可能会看到很多 NoClassDefFoundErrors 当您: throw A. RuntimeExceptionstatic 你们班的学生 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 全班只掷硬币 NoClassDefFoundErrors .

mpbci0fu

mpbci0fu12#

当运行时类加载器加载的类无法访问java rootloader已经加载的类时,我得到noclassfounderror。因为不同的类加载器位于不同的安全域(根据java),所以jvm不允许在运行时加载器地址空间中解析已经由rootloader加载的类。
使用“java-javaagent:tracer.jar[您的java参数]运行您的程序”
它生成显示加载的类和加载该类的loader 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;
            }
        });
    }
}
tkqqtvp1

tkqqtvp113#

下面的技巧多次帮助了我:

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

其中,Thenodeffound类是由于您的程序使用的相同库的较旧版本而可能“丢失”的类。这种情况最常见的情况是,客户机软件被部署到一个占主导地位的容器中,该容器配备有自己的类加载器和大量最流行的libs的古老版本。

2cmtqfgy

2cmtqfgy14#

在生成代码(emf等)的情况下,可能会有太多的静态初始化器,它们会占用所有堆栈空间。
请参阅堆栈溢出问题如何增加java堆栈大小?。

8yoxcaq7

8yoxcaq715#

同一项目的两个不同 checkout 副本

在我的例子中,问题在于eclipse无法区分同一项目的两个不同副本。我有一个锁在 Backbone.js 上(svn版本控制),另一个一次在一个分支上工作。作为junit测试用例,我在工作副本中尝试了一个更改,其中包括将一个私有内部类单独提取为一个公共类,当它工作时,我打开项目的另一个副本,查看需要更改的代码的其他部分。在某个时候 NoClassDefFoundError 突然出现,抱怨私人内部阶级不在那里;双击堆栈跟踪使我找到了错误项目副本中的源文件。
关闭项目的 Backbone.js 副本并再次运行测试用例可以解决这个问题。

相关问题