258

我已经尝试了 Oracle 的Java 教程中的两个示例。它们都编译得很好,但是在运行时,都出现了这个错误:

Exception in thread "main" java.lang.NoClassDefFoundError: graphics/shapes/Square
    at Main.main(Main.java:7)
Caused by: java.lang.ClassNotFoundException: graphics.shapes.Square
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 1 more

我想我可能将Main.java文件放在错误的文件夹中。

这是目录层次结构:

graphics
├ Main.java
├ shapes
|   ├ Square.java
|   ├ Triangle.java
├ linepoint
|   ├ Line.java
|   ├ Point.java
├ spaceobjects
|   ├ Cube.java
|   ├ RectPrism.java

这是Main.java

import graphics.shapes.*;
import graphics.linepoint.*
import graphics.spaceobjects.*;

public class Main {
    public static void main(String args[]) {
        Square s = new Square(2, 3, 15);
        Line l = new Line(1, 5, 2, 3);
        Cube c = new Cube(13, 32, 22);
    }
}

我在这里做错了什么?

更新

在我将Main类放入graphics包中(我添加package graphics;到它中)后,将类路径设置为“_test”(包含图形的文件夹),编译它,并使用java graphics.Main(从命令行)运行它,它工作了。

真的很晚更新#2

我没有使用Eclipse(只是Notepad++和 JDK),上面的更新解决了我的问题。但是,似乎其中许多答案是针对 Eclipse 和IntelliJ IDEA的,但它们具有相似的概念。

4

31 回答 31

269

编译代码后,您最终会得到.class程序中每个类的文件。这些二进制文件是 Java 解释以执行您的程序的字节码。NoClassDefFoundError表示负责动态加载类的类加载器(在本例中)java.net.URLClassLoader找不到.class您尝试使用的类的文件。

如果所需的类不存在(除非使用反射加载类),您的代码将无法编译,因此通常此异常意味着您的类路径不包含所需的类。请记住,类加载器(特别是java.net.URLClassLoader)将在类路径的每个条目中的文件夹 a/b/c/ 中的包 abc 中查找类。NoClassDefFoundError还可以表明您缺少已编译并尝试使用的 .jar 文件的传递依赖项。

例如,如果你有一个类com.example.Foo,编译后你会有一个类文件Foo.class。比如说你的工作目录是.../project/. 该类文件必须放在 中.../project/com/example,并且您可以将类路径设置为.../project/.

旁注:我建议利用 Java 和 JVM 语言中存在的惊人工具。Eclipse 和 IntelliJ IDEA 等现代 IDE 以及 Maven 或 Gradle 等构建管理工具将帮助您不必(尽可能多地)担心类路径并专注于代码!也就是说,这个链接解释了如何在命令行上执行时设置类路径。

于 2013-07-31T15:05:05.550 回答
152

我想纠正其他人的观点NoClassDefFoundError

NoClassDefFoundError可能由于多种原因发生,例如:

  1. ClassNotFoundException - .class 找不到该引用的类,无论它在编译时是否可用(即基类/子类)。
  2. 已找到类文件,但在初始化静态变量时引发异常
  3. 找到类文件,初始化静态块时引发异常

在最初的问题中,这是第一种可以通过将 CLASSPATH 设置为引用的类 JAR 文件或其包文件夹来纠正的情况。

说“在编译时可用”是什么意思?

  • 引用的类在代码中使用。
    例如:两个类,A 和 B(扩展 A)。如果在代码中直接引用了 B,则它在编译时可用,即A a = new B();

说“在编译时不可用”是什么意思?

  • 编译时类和运行时类是不同的,例如,使用子类的类名加载基类,例如 Class.forName("classname") 例如:两个类,A 和 B(扩展 A)。代码有
    A a = Class.forName("B").newInstance();
于 2014-01-23T09:09:08.117 回答
18

NoClassDefFoundError表示该类存在于 的类路径中Compile time,但它不存在于 的类路径中Runtime

如果您使用的是 Eclipse,请确保文件中有shapes,linepointsspaceobjectsas 条目.classpath

于 2013-07-31T15:02:26.897 回答
16

如果您在编译和运行时遇到以下错误之一:

  • NoClassDefFoundError

  • 错误:无法找到或加载主类你好

  • 线程“主”java.lang.NoClassDefFoundError:javaTest/test/hello 中的异常(错误名称:test/hello)

    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(Unknown Source)
    at java.security.SecureClassLoader.defineClass(Unknown Source)
    at java.net.URLClassLoader.defineClass(Unknown Source)
    at java.net.URLClassLoader.access$100(Unknown Source)
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)
    

--------------------------解决方案------------

问题主要在于包组织。您应该根据源代码中的包分类正确地将您的类安排在文件夹中。

在编译过程中,使用以下命令:

javac -d . [FileName.java]

要运行该类,请使用以下命令:

java [Package].[ClassName]
于 2014-10-07T11:23:51.437 回答
10
java.lang.NoClassDefFoundError

表示在编译时找到了某些东西,但在运行时没有找到。也许您只需要将它添加到类路径中。

于 2013-07-31T15:03:00.453 回答
8

当在类路径中找不到预期的类时,会发生无类定义异常。

在编译时类:类是从 Java 编译器生成的,但不知何故在运行时找不到依赖类。

让我们来看一个简单的例子:

public class ClassA{
    public static void main(String args[]){
         // Some gibberish code...
         String text = ClassB.getString();
         System.out.println("Text is: " + text);
    }
}

public class ClassB{
    public static String getString(){
        return "Testing some exception";
    }
}

现在让我们假设上面两个Java源代码放在某个文件夹中,比如说“NoClassDefinationFoundExceptionDemo”

现在打开一个 shell(假设 Java 已经正确设置)

  1. 转到文件夹“NoClassDefinationFoundExceptionDemo”

  2. 编译 Java 源文件 javac ClassB javac ClassA

  3. 两个文件都编译成功,并在ClassA.class和ClassB.class的同一文件夹中生成了类文件

  4. 现在,由于我们将 ClassPath 覆盖到当前的工作主管,我们执行以下命令 java -cp 。ClassA 并成功运行,您将在屏幕上看到输出

  5. 现在假设您从当前目录中删除了 ClassB.class 文件。现在你再次执行命令。 爪哇-cp。ClassA现在它会以 NoClassDefFoundException 迎接你。因为在类路径(即当前工作目录)中找不到作为 ClassA 依赖项的 ClassB。

于 2015-03-22T16:28:32.180 回答
8

Java 中的 NoClassDefFoundError:

定义:

如果在编译期间存在类但在运行期间在 java 类路径中不可用,则会出现 NoClassDefFoundError。通常,当您收到 NoClassDefFoundError: Exception in thread "main" java.lang.NoClassDefFoundError 时,您会在日志中看到以下行

可能的原因:

  1. 该类在 Java 类路径中不可用。

  2. 您可能正在使用 jar 命令运行程序,并且清单文件的 ClassPath 属性中未定义类。

  3. 任何启动脚本都会覆盖 Classpath 环境变量。

  4. 因为 NoClassDefFoundError 是 java.lang.LinkageError 的子类,所以如果其中一个依赖项(如本机库)可能不可用,它也会出现。

  5. 检查日志文件中的 java.lang.ExceptionInInitializerError。由于静态初始化失败导致的 NoClassDefFoundError 很常见。

  6. 如果您在 J2EE 环境中工作,多个 Classloader 之间的 Class 的可见性也会导致 java.lang.NoClassDefFoundError,请参阅示例和场景部分进行详细讨论。

可能的解决方案:

  1. 验证所有必需的 Java 类都包含在应用程序的类路径中。最常见的错误是在开始执行依赖于某些外部库的 Java 应用程序之前没有包含所有必要的类。

  2. 应用程序的类路径是正确的,但是在应用程序执行之前 Classpath 环境变量被覆盖。

  3. 验证前面提到的 ExceptionInInitializerError 没有出现在应用程序的堆栈跟踪中。

资源:

解决 Java J2EE 中 java.lang.NoClassDefFoundError 的 3 种方法

java.lang.NoClassDefFoundError – 如何解决 No Class Def Found 错误

于 2016-08-08T08:19:18.870 回答
4

如果您的项目位于类似的包中,com.blahcode并且调用了您的类Main,则编译后的文件可能会以类似的目录结构输出./out/com/blahcode/Main.class。对于 IntelliJ IDEA 尤其如此。

当尝试从 shell 或 cmd 运行时,您需要将cd其包含com为子目录。

cd out
java -classpath . com.blahcode.Main
于 2014-09-27T23:32:39.010 回答
2

在从事 NetBeans 项目数月后,我在收到“内存不足”警报后不久突然收到 NoClassDefFoundError 消息。进行干净的重建没有帮助,但是完全关闭 NetBeans 并重新打开项目没有错误报告。

于 2016-04-14T13:51:35.073 回答
2

此答案特定于服务中发生的 java.lang.NoClassDefFoundError :

我的团队最近在升级提供服务的 rpm 后发现了这个错误。rpm 和其中的软件是用 Maven 构建的,所以看起来我们有一个编译时依赖项,它刚刚没有包含在 rpm 中。

但是,在调查时,未找到的类与堆栈跟踪中的几个类位于同一模块中。此外,这不是最近才添加到构建中的模块。这些事实表明它可能不是 Maven 依赖问题。

最终解决方案:重启服务!

似乎 rpm 升级使基础 JAR 文件上的服务文件句柄无效。然后,该服务看到一个尚未加载到内存中的类,在其 jar 文件句柄列表中搜索它,但未能找到它,因为它可以从中加载类的文件句柄已失效。重新启动服务会强制它重新加载所有文件句柄,然后允许它加载在 rpm 升级后尚未在内存中找到的类。

于 2016-12-02T16:33:37.350 回答
2

我今天遇到了这个问题。我有一个 Android 项目,启用multidex该项目后将不再启动。

原因是我忘记调用应该添加到的特定 multidex 方法,Application class并在其他所有操作之前调用。

 MultiDex.install(this);

按照本教程正确启用 multidex。https://developer.android.com/studio/build/multidex.html

您应该将这些行添加到您的 Application 类

 @Override
  protected void attachBaseContext(Context base) {
     super.attachBaseContext(base);
     MultiDex.install(this);
  }
于 2017-11-24T14:50:29.180 回答
2

对于我的项目,解决问题的是 Chrome 浏览器和 chromedriver 不兼容。我有一个非常旧的驱动程序版本,甚至无法打开浏览器。我刚刚下载了两者的最新版本并解决了问题。

我是如何发现问题的?因为我使用 Selenium 本机 Firefox 驱动程序和我的应用程序中包含的旧版本 FF 运行我的项目。我意识到问题是浏览器和驱动程序之间的不兼容。

希望这可以帮助任何与我有类似问题的人,这会产生相同的错误消息。

于 2019-01-04T19:37:58.833 回答
2

如果您从 JAR 文件“启动”一个类,请确保从 JAR 完整路径开始。例如,(如果清单中未指定您的“主类”):

java -classpath "./dialer.jar" com.company.dialer.DialerServer

并且如果有任何依赖,比如对其他JAR文件的依赖,你可以解决这样的依赖

  • 通过将此类 JAR 文件(每个 JAR 文件的完整路径)添加到类路径中。例如,
java -classpath "./libs/phone.jar;./libs/anotherlib.jar;./dialer.jar" com.company.dialer.DialerServer
  • 或者通过在清单中添加“依赖 JAR 文件”来编辑 JAR 清单。这样的清单文件可能如下所示:
Manifest-Version: 1.0
Class-Path: phone.jar anotherlib.jar
Build-Jdk-Spec: 1.8
Main-Class: com.company.dialer.DialerServer
  • 或者(如果您是拥有源代码的开发人员)您可以使用 Maven 通过添加到 *.pom 文件来为您准备清单:
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <configuration>
        <archive>
            <manifest>
                <addClasspath>true</addClasspath>
                <mainClass>com.company.dialer.DialerServer</mainClass>
                <!-- Workaround for Maven bug #MJAR-156 (https://jira.codehaus.org/browse/MJAR-156) -->
                <useUniqueVersions>false</useUniqueVersions>
            </manifest>
        </archive>
    </configuration>
</plugin>

请注意,上面的示例;在类路径中用作分隔符(适用于 Windows 平台)。在 Linux 上,替换;:.

例如,

java -classpath ./libs/phone.jar:./libs/anotherlib.jar:./dialer.jar
com.company.dialer.DialerServer
于 2021-05-28T08:21:18.663 回答
1

我在使用 Android Studio 进行 Android 开发时遇到了同样的问题。提供的解决方案是一般性的,并没有帮助我(至少对我而言)。

经过数小时的研究,我找到了以下解决方案,它可能对使用 Android Studio 进行开发的 Android 开发人员有所帮助。

修改设置如下:

首选项构建、执行、部署即时运行→ *取消选中第一个选项。

有了这个改变,我就可以开始运行了。

于 2016-04-28T17:29:43.087 回答
1

如果你使用多个模块,你应该有

dexOptions {
    preDexLibraries = false
}

在您的构建文件中。

于 2017-04-20T08:47:45.823 回答
1

我正在开发一个基于 Eclipse 的应用程序,也称为RCP (Rich Client Platform)。在重构之后我一直面临着这个问题(将一个类从一个插件移动到一个新的类)。

清理项目和 Maven 更新没有帮助。

该问题是由尚未自动更新的Bundle-Activator引起的。在新插件中手动更新MANIFEST.MF下的 Bundle-Activator解决了我的问题。

于 2018-04-06T08:41:28.757 回答
0

我在这条链中的两分钱:

确保类路径包含完整路径(/home/user/lib/some_lib.jar而不是~/lib/some_lib.jar),否则您仍然会遇到NoClassDefFoundError错误。

于 2015-06-17T15:02:50.690 回答
0

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

使用 'java -javaagent:tracer.jar [YOUR 'java' ARGUMENTS]' 运行程序

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

// 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;
            }
        });
    }
}
于 2015-09-09T11:56:14.570 回答
0

它发生在我的Android Studio中。

对我有用的解决方案:只需重新启动 Android Studio。

于 2016-04-13T11:21:16.390 回答
0

检查您的班级中是否有静态处理程序。如果是这样,请小心,因为静态处理程序只能在具有循环器的线程中启动,崩溃可以通过这种方式触发:

  1. 首先,在一个简单的线程中创建类的实例并捕获崩溃。

  2. 然后在主线程调用Class的field方法,会得到NoClassDefFoundError。

这是测试代码:

public class MyClass{
       private static  Handler mHandler = new Handler();
       public static int num = 0;
}

在 Main 活动的 onCreate 方法中,添加测试代码部分:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    //test code start
    new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                MyClass myClass = new MyClass();
            } catch (Throwable e) {
                e.printStackTrace();
            }
        }
    }).start();

    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    MyClass.num = 3;
    // end of test code
}

有一种简单的方法可以使用 handlerThread 到 init 处理程序来修复它:

private static Handler mHandler;
private static HandlerThread handlerThread = new HandlerThread("newthread");
static {
    handlerThread.start();
    mHandler = new Handler(handlerThread.getLooper(), mHandlerCB);
}
于 2017-01-16T03:51:37.633 回答
0

此异常的一个错误来源可能源于Proguard的不一致定义,例如缺少

-libraryJars “path.to.a.missing.jar.library”。

这解释了为什么编译和运行工作正常,因为 JAR 文件在那里,而清理和构建失败。请记住在 ProGuard 设置中定义新添加的 JAR 库!

请注意,来自 ProGuard 的错误消息确实不符合标准,因为当 JAR 文件根本不存在时,它们很容易与到达的类似Ant消息混淆。只有在最底层才会有一点点 ProGuard 的麻烦。因此,开始搜索传统的类路径错误等是很合乎逻辑的,但这将是徒劳的。

显然,NoClassDefFound 异常将是运行时的结果,例如,生成的可执行 JAR 文件基于缺乏 ProGuard 一致性而构建。有人称它为 ProGuard “地狱”。

于 2017-11-02T20:04:06.467 回答
0

我使用Eclipse 的 FileSync 插件,所以我可以在 Tomcat 上进行实时调试。我收到了NoClassFoundError,因为我在 Tomcatbin中为 Eclipse 工作区中的目录=> classes添加了同步条目metadata,但我还没有为extlibEclipse 中的目录添加文件夹同步=>

C:\Users\Stuart\eclipse-workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\webapps\myApp\WEB-INF\lib

于 2017-12-06T10:56:16.960 回答
0

如果您最近在 Android Studio 中添加了 multidex 支持,如下所示:

// To support MultiDex
implementation 'com.android.support:multidex:1.0.1'

因此,您的解决方案只是从 MultiDexApplication 而不是 Application 扩展:

public class MyApp extends MultiDexApplication {
于 2018-04-30T06:36:14.797 回答
0

不要在模块外使用测试类

我没有解决方案,只是另一种“编译时存在,运行时不存在”的情况。

我试图从驻留在不同模块中的另一个测试类的 JUnit 测试类中使用一种非常方便的方法。这是一个禁忌,因为测试代码不是打包 jar 的一部分,但我没有意识到,因为它对 Eclipse 中的用户类是可见的。

我的解决方案是将方法放在作为生产代码一部分的现有实用程序类中。

于 2019-12-05T16:01:42.260 回答
0

在我的环境中,我在单元测试中遇到了这个问题。将一个库依赖项附加到 *.pom 后,就解决了。

例子:

错误信息:

java.lang.NoClassDefFoundError: com/abc/def/foo/xyz/Iottt

POM内容:

<dependency>
    <groupId>com.abc.def</groupId>
    <artifactId>foo</artifactId>
    <scope>test</scope>
</dependency>
于 2020-04-08T06:59:17.013 回答
0

Git 分支更改后出现此错误。对于 Eclipse 的特定情况,在.settings目录中缺少org.eclipse.wst.common.component 文件的行。正如你在下面看到的。

使用 Maven install 恢复项目依赖项会有所帮助。

在此处输入图像描述

于 2020-05-20T01:54:05.770 回答
0

如果您正在使用gradlew,请转到./gradle/wrapper/gradle-wrapper.properties并更改distributionUrl为正确版本的Gradle

如果您使用的是 JDK14,请尝试:

distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-bin.zip
于 2020-06-28T12:25:49.227 回答
0

对于MeteorCordova用户,

它可能是由您使用的 Java 版本引起的。对于 Meteor 和 Cordova,暂时坚持使用版本 8。

  1. 检查可用的 Java 版本/usr/libexec/java_home -V 并查找 Java 版本 8 的路径名

  2. 设置 Java 版本 8 的路径 export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home

  3. 检查是否完成 echo $JAVA_HOME

继续并继续编码。

于 2021-01-18T07:50:21.810 回答
0

Java 11 + Eclipse 解决方案:

如果您没有module-info.java在 Eclipse 项目中使用此解决方案,并且您手动添加了 JAR 文件而不是使用Maven / Gradle ,则此解决方案适合您。

  1. 右键单击项目→构建路径配置构建路径选项卡
  2. 从模块路径中删除有问题的 JAR 文件
  3. 将 JAR 文件添加到类路径

更多信息 在 Eclipse 中,modulepath 和 classpath 有什么区别?.

于 2021-04-22T22:02:15.797 回答
-1

我的Genymotion设备经常发生这种情况。

确保安装 Genymotion 的驱动器上有足够的可用内存。

于 2016-01-12T09:10:32.893 回答
-2

此错误意味着您没有添加某些依赖项。

于 2021-02-07T15:24:11.503 回答