为什么我在java中遇到noclassdeffounderror?

dohp0rv5  于 2021-06-24  发布在  Flink
关注(0)|答案(17)|浏览(469)

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

hzbexzde

hzbexzde1#

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

set classpath=%classpath%;axis.jar

我可以通过使用以下方法使其获得正确的版本:

set classpath=axis.jar;%classpath%;
zzzyeukh

zzzyeukh2#

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

ljsrvy3e3#

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

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

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

3duebb1j

3duebb1j4#

一个有趣的例子,你可能会看到很多 NoClassDefFoundErrors 当您: throwRuntimeExceptionstatic 你们班的学生 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 .

xxslljrj

xxslljrj5#

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

dexOptions {
        preDexLibraries false
        ...
ig9co6j1

ig9co6j16#

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

5fjcxozz

5fjcxozz7#

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

83qze16e

83qze16e8#

当运行时类加载器加载的类无法访问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;
            }
        });
    }
}
41ik7eoe

41ik7eoe9#

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

示例:
类不在类路径中,没有确定的方法知道它,但是很多时候你可以只看一下打印system.getproperty(“java.classpath”),它会打印类路径,从那里你至少可以了解实际的运行时类路径。
noclassdeffounderror的一个简单例子是类属于一个丢失的jar文件,或者jar没有添加到类路径中,或者有时jar的名称被某人更改了,比如在我的例子中,我的一个同事将tibco.jar更改为tibco\u 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问题模式

m0rkklqb

m0rkklqb10#

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

bqjvbblv11#

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

z31licg0

z31licg012#

当我将另一个模块的maven依赖项添加到我的项目中时,我遇到了这个错误,这个问题最终通过add解决了 -Xss2m 添加到我的程序的jvm选项(自jdk5.0以来,默认值是1兆字节)。据信程序没有足够的堆栈来加载类。

ycl3bljg

ycl3bljg13#

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

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

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

k3bvogb1

k3bvogb114#

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

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

flseospp

flseospp15#

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

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

相关问题