如何解决java.lang.NoClassDefFoundError?

时间:2013-07-31 15:00:28

标签: java exception packages noclassdeffounderror

我在Oracle的Java Tutorials中尝试过这两个例子。它们都编译得很好,但在运行时,都会出现这个错误:

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的,但它们有类似的概念。

31 个答案:

答案 0 :(得分:193)

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

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

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

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

答案 1 :(得分:117)

我想在NoClassDefFoundError上更正其他人的观点。

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

  1. ClassNotFoundException - 找不到该引用类的.class,无论它是否在编译时可用(即base / child class)。
  2. 找到类文件,但在初始化静态变量时引发了异常
  3. 找到类文件,初始化静态块时引发异常
  4. 在最初的问题中,这是第一个可以通过将CLASSPATH设置为引用的类jar文件或其包文件夹来纠正的情况。

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

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

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

    • 编译时类和运行时类是不同的,例如,例如,使用子类的类名加载基类 的Class.forName( “类名”)
      例如:两个类,A和B(扩展A)。代码有 A = Class.forName(“B”)。newInstance();

答案 2 :(得分:12)

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

如果您使用的是Eclipse,请确保shapes文件中包含linepointsspaceobjects.classpath作为条目。

答案 3 :(得分:11)

如果在编译和运行时遇到其中一个错误:

* NoClassDefFoundError

* Error: Could not find or load main class hello

* Exception in thread "main" java.lang.NoClassDefFoundError:javaTest/test/hello 
(wrong name: 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)

-------------------------- SOLUTIION ------ -----------------

问题主要出在包装组织中。您应该在文件夹中正确安排有关源代码中的包分类的类。

On Compiling process use this command:

javac -d . [FileName.java]

To Run the class please use this command:

java [Package].[ClassName]

答案 4 :(得分:8)

java.lang.NoClassDefFoundError

表示在 compiletime 但未在运行时找到了某些内容。也许你只需要将它添加到类路径中。

答案 5 :(得分:6)

当在类路径中找不到目标类时,会发生

没有类定义异常。 在编译时类:类是从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. 两个文件都已成功编译并在同一个文件夹中生成了Class文件 作为ClassA.class和ClassB.class
  4. 现在我们将ClassPath重写为当前工作目录 因此我们执行以下命令 java -cp。 ClassA的 并且它成功运行,您将在屏幕上看到输出
  5. 现在让我们说,您从Present Directory中删除了ClassB.class文件。 现在你再次执行命令。 java -cp。 ClassA 现在它将使用NoClassDefFoundException来迎接你。因为在类路径(即工作目录)中找不到作为ClassA依赖关系的ClassB。

答案 6 :(得分:2)

如果您的项目位于com.blahcode之类的包中,并且您的类名为Main,则编译后的文件可能会在./out/com/blahcode/Main.class这样的目录结构中输出。对于IntelliJ IDEA尤其如此。

尝试从shell或cmd运行时,需要cd到包含com的子目录。

cd out
java -classpath . com.blahcode.Main

答案 7 :(得分:2)

Java中的NoClassDefFoundError:

定义:

如果在编译期间存在类但在运行时期间在java类路径中不可用,则会出现NoClassDefFoundError。通常,当您获得NoClassDefFoundError时,您将在日志中看到以下行: 线程" main"中的例外情况java.lang.NoClassDefFoundError

可能的原因:

  1. 该类在Java Classpath中不可用。

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

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

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

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

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

  7. 可能的解决方案:

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

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

    3. 验证上述ExceptionInInitializerError未出现在应用程序的堆栈跟踪中。

    4. 资源:

      3 ways to solve java.lang.NoClassDefFoundError in Java J2EE

      java.lang.NoClassDefFoundError – How to solve No Class Def Found Error

答案 8 :(得分:1)

对于我的项目,解决问题的是Chrome浏览器和chromedriver不兼容。我的驱动程序版本太旧,甚至无法打开浏览器。我刚刚下载了两者的最新版本,并解决了问题。我是如何发现问题的?因为我使用Selenium本机firefox驱动程序运行了项目,并且将旧版本的FF与我的应用程序结合在一起,所以我意识到问题出在浏览器和驱动程序之间不兼容。

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

答案 9 :(得分:1)

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

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

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

答案 10 :(得分:1)

在处理NetBeans项目好几个月之后,我在收到“低内存”警报后不久就突然收到NoClassDefFoundError消息。做一个干净的重建没有帮助,但完全关闭Netbeans并重新打开项目没有错误报告。

答案 11 :(得分:1)

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

我的团队最近在升级提供服务的rpm后看到了这个错误。 rpm和它内部的软件都是用Maven构建的,所以我们似乎有一个编译时依赖项,而这个依赖项还没有包含在rpm中。

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

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

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

希望具体案例有助于某人。

答案 12 :(得分:0)

如果您最近在Android studio中添加了multidex支持,请执行以下操作:

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

所以你的解决方案只是从MultiDexApplication而不是Application

扩展
public class MyApp extends MultiDexApplication {

答案 13 :(得分:0)

如果您要从 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>
            </manifest>
        </archive>
    </configuration>
</plugin>

请注意,上面的示例使用 ; 作为 classpath 中的分隔符(它对 Windows 平台有效)。在 Linux 上,将 ; 替换为 :

例如

java -classpath ./libs/phone.jar:./libs/anotherlib.jar:./dialer.jar
com.company.dialer.DialerServer

答案 14 :(得分:0)

请勿在模块外部使用测试类

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

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

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

答案 15 :(得分: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>

答案 16 :(得分:0)

更改Git分支后出现此错误。对于Eclipse的特定情况,org.eclipse.wst.common.component文件的.settings目录中缺少行。如您所见

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

enter image description here

答案 17 :(得分:0)

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

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

distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-bin.zip

答案 18 :(得分: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

继续编码。

答案 19 :(得分:0)

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

答案 20 :(得分:0)

Java 11 + Eclipse 解决方案:

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

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

更多信息在 In Eclipse, what is the difference between modulepath and classpath?

答案 21 :(得分:0)

我正在开发一个基于Eclipse的应用程序,也称为 RCP(富客户端平台)。 重构后我一直面临这个问题(将一个类从一个插件移到一个新的插件中)。

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

问题是由 Bundle-Activator 引起的,它没有自动更新。在新的PlugIn中手动更新 MANIFEST.MF 下的Bundle-Activator修复了我的问题。

答案 22 :(得分:0)

我使用enter image description here所以我可以在Tomcat&amp;我收到了NoClassFoundError,因为我在Tomcat bin的Eclipse工作区=> classes中添加了metadata目录的同步条目,但还没有添加文件夹同步Eclipse extlib

中的=>目录

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

答案 23 :(得分:0)

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

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

这解释了为什么编译和运行工作正常,因为罐子在那里,而干净&amp;构建失败。记得在proguard设置中定义新添加的jar库!

请注意,来自Proguard的错误消息实际上不符合标准,因为它们很容易与罐子根本不存在时到达的类似ant消息混淆。只有在最底层才会出现一些麻烦的提示。因此,开始搜索传统的类路径错误等是非常逻辑的,但这将是徒劳的。

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

答案 24 :(得分:0)

如果您使用多个模块,则应该

dexOptions {
    preDexLibraries = false
}

在您的构建文件中。

答案 25 :(得分:0)

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

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

2.然后在主线程中调用Class的field方法,你将获得NoClassDefFoundError。

这是测试代码:

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

在主要活动的onCrete方法中,添加测试代码部分:

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

答案 26 :(得分:0)

我使用Android studio进行Android开发时遇到了同样的问题。 提供的解决方案是一般的,并没有帮助我(至少对我来说)。 经过几个小时的研究后,我找到了以下解决方案,可能对使用android studio进行开发的android开发人员有所帮助。 修改设置如下 首选项 - &gt;构建,执行,部署 - &gt;即时运行 - &gt;取消检查第一个选项。

有了这个改变,我就开始了。 希望这能帮助我的开发朋友。

答案 27 :(得分:0)

Android Studio中发生了这件事。

对我有用的解决方案: 只需重新启动工作室。

答案 28 :(得分:0)

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

使用&#39; java -javaagent:tracer.jar运行您的程序[您的Java ARGS]&#39;

它生成显示已加载类的输出,以及加载类的加载器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;
            }
        });
    }
}

答案 29 :(得分:0)

我在这条链中的两分钱:

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

答案 30 :(得分:-1)

我的genymotion设备发生了很多事情。 确保安装了Genymotion的驱动器上有足够的可用内存。