为什么我在 Java 中收到 NoClassDefFoundError 错误?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/34413/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 07:26:00  来源:igfitidea点击:

Why am I getting a NoClassDefFoundError in Java?

javanoclassdeffounderror

提问by John Meagher

I am getting a NoClassDefFoundErrorwhen I run my Java application. What is typically the cause of this?

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

采纳答案by Mocky

This is caused when there is a class file that your code depends on and it is present at compile time but not found at runtime. Look for differences in your build time and runtime classpaths.

这是由于存在您的代码所依赖的类文件并且它在编译时存在但在运行时未找到时引起的。寻找构建时间和运行时类路径的差异。

回答by shsteimer

I have found that sometimes I get a NoClassDefFound error when code is compiled with an incompatible version of the class found at runtime. The specific instance I recall is with the apache axis library. There were actually 2 versions on my runtime classpath and it was picking up the out of date and incompatible version and not the correct one, causing a NoClassDefFound error. This was in a command line app where I was using a command similar to this.

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

set classpath=%classpath%;axis.jar

I was able to get it to pick up the proper version by using:

我能够通过使用它来获取正确的版本:

set classpath=axis.jar;%classpath%;

回答by Jared

While it's possible that this is due to a classpath mismatch between compile-time and run-time, it's not necessarily true.

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

It is important to keep two or three different exceptions straight in our head in this case:

在这种情况下,我们必须牢记两三个不同的例外:

  1. java.lang.ClassNotFoundExceptionThis exception indicates that the class was not found on the classpath. This indicates that we were trying to load the class definition, and the class did not exist on the classpath.

  2. java.lang.NoClassDefFoundErrorThis exception indicates that the JVM looked in its internal class definition data structure for the definition of a class and did not find it. This is different than saying that it could not be loaded from the classpath. Usually this indicates that we previously attempted to load a class from the classpath, but it failed for some reason - now we're trying to use the class again (and thus need to load it, since it failed last time), but we're not even going to try to load it, because we failed loading it earlier (and reasonably suspect that we would fail again). The earlier failure could be a ClassNotFoundException or an ExceptionInInitializerError (indicating a failure in the static initialization block) or any number of other problems. The point is, a NoClassDefFoundError is not necessarily a classpath problem.

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

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

回答by xli

Here is the code to illustrate java.lang.NoClassDefFoundError. Please see Jared's answerfor detailed explanation.

这是用于说明的代码java.lang.NoClassDefFoundError。有关详细说明,请参阅Jared 的回答

NoClassDefFoundErrorDemo.java

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

简单计算器.java

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

回答by Nikhil Sahu

I was using Spring Frameworkwith Mavenand solved this error in my project.

我使用Spring框架Maven的,在我的项目解决了这个错误。

There was a runtime error in the class. I was reading a property as integer, but when it read the value from the property file, its value was double.

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

Spring did not give me a full stack trace of on which line the runtime failed. It simply said NoClassDefFoundError. But when I executed it as a native Java application (taking it out of MVC), it gave ExceptionInInitializerErrorwhich was the true cause and which is how I traced the error.

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

@xli's answer gave me insight into what may be wrong in my code.

@xli 的回答让我深入了解我的代码中可能有什么问题。

回答by codeDr

I get NoClassFoundError when classes loaded by the runtime class loader cannot access classes already loaded by the java rootloader. Because the different class loaders are in different security domains (according to java) the jvm won't allow classes already loaded by the rootloader to be resolved in the runtime loader address space.

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

Run your program with 'java -javaagent:tracer.jar [YOUR java ARGS]'

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

It produces output showing the loaded class, and the loader env that loaded the class. It's very helpful tracing why a class cannot be resolved.

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

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

回答by Ram Patra

This is the best solutionI found so far.

这是我目前找到的最好的解决方案

Suppose we have a package called org.mypackagecontaining the classes:

假设我们有一个org.mypackage包含类的包:

  • HelloWorld (main class)
  • SupportClass
  • UtilClass
  • HelloWorld(主类)
  • 支持类
  • 实用类

and the files defining this package are stored physically under the directory D:\myprogram(on Windows) or /home/user/myprogram(on Linux).

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

The file structure will look like this: enter image description here

文件结构将如下所示: 在此处输入图片说明

When we invoke Java, we specify the name of the application to run: org.mypackage.HelloWorld. However we must also tell Java where to look for the files and directories defining our package. So to launch the program, we have to use the following command: enter image description here

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

回答by Eliran

I got this message after removing two files from the SRC library, and when I brought them back I kept seeing this error message.

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

My solution was: Restart Eclipse. Since then I haven't seen this message again :-)

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

回答by Alex

Make sure this matches in the module:appand module:lib:

确保这在module:app和 中匹配module:lib

android {
    compileSdkVersion 23
    buildToolsVersion '22.0.1'
    packagingOptions {
    }

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

回答by sudar

I had the same problem, and I was stock for many hours.

我遇到了同样的问题,我库存了好几个小时。

I found the solution. In my case, there was the static method defined due to that. The JVM can not create the another object of that class.

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

For example,

例如,

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