如何解决“java.lang.NoClassDefFoundError”?

如何解决“java.lang.NoClassDefFoundError”?,java,exception,package,noclassdeffounderror,Java,Exception,Package,Noclassdeffounderror,这两个例子我都试过了。它们都可以很好地编译,但在运行时都会出现以下错误: 线程主java.lang.NoClassDefFoundError中出现异常:graphics/shapes/Square Main.mainMain.java:7 原因:java.lang.ClassNotFoundException:graphics.shapes.Square 在java.net.URLClassLoader$1.runURLClassLoader.java:366 在java.net.URLClas

这两个例子我都试过了。它们都可以很好地编译,但在运行时都会出现以下错误:

线程主java.lang.NoClassDefFoundError中出现异常:graphics/shapes/Square Main.mainMain.java:7 原因:java.lang.ClassNotFoundException:graphics.shapes.Square 在java.net.URLClassLoader$1.runURLClassLoader.java:366 在java.net.URLClassLoader$1.runURLClassLoader.java:355 位于java.security.AccessController.doPrivilegeEdNative方法 位于java.net.URLClassLoader.findClassURLClassLoader.java:354 位于java.lang.ClassLoader.LoadClassLoader.java:424 位于sun.misc.Launcher$AppClassLoader.loadClassLauncher.java:308 位于java.lang.ClassLoader.LoadClassLoader.java:357 ... 还有一个 我想我可能把Main.java文件放错文件夹了

以下是目录层次结构:

图样 ├ 主类 ├ 形状 | ├ Square.java | ├ Triangle.java ├ 线条点 | ├ Line.java | ├ Point.java ├ 空间物体 | ├ java | ├ RectPrism.java 下面是Main.java:

我做错了什么

更新

在我将主类放入图形包之后,我添加了图形包;为此,将类路径设置为包含图形的_test文件夹,编译它,并使用java graphics.Main从命令行运行它

真的很晚更新2

我没有使用just和JDK,上面的更新解决了我的问题。然而,这些答案中似乎有许多是针对Eclipse和的,但它们有相似的概念。

NoClassDefFoundError意味着类在编译时存在于类路径中,但在运行时不存在于类路径中

如果您使用的是Eclipse,请确保在.classpath文件中有形状、线条点和空间对象作为条目


指示在编译时找到了某些内容,但在运行时找不到。也许您只需要将其添加到类路径中。

编译代码后,程序中的每个类都会有.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语言的惊人工具。Eclipse和IntelliJ IDEA等现代IDE以及Maven或Gradle等构建管理工具将帮助您不必担心类路径,而只需关注代码!也就是说,解释了在命令行上执行时如何设置类路径。

我想纠正其他人对NoClassDefFoundError的看法

NoClassDefFoundError发生的原因有多种,如:

ClassNotFoundException-.未找到该引用类的类,无论该类是否在编译时可用或是否在基类/子类中可用。 已找到类文件,但初始化静态变量时引发异常 已找到类文件,初始化静态块时引发异常 在最初的问题中,这是第一种可以通过将类路径设置为引用的类JAR文件或其包文件夹来纠正的情况

编译时可用是什么意思

代码中使用了引用的类。例如:两个类,A和B扩展了A。如果B在代码中直接引用,则在编译时可用,即A=新B; 说编译时不可用是什么意思

编译时类和运行时类是不同的,例如,基类是使用子类的classname加载的 Class.forNameclassname 例如:两个类,A和B扩展了A。代码有 A=Class.forNameB.newInstance;
如果您的项目位于com.blahcode这样的包中,并且您的类被称为Main,那么编译后的文件可能会以类似于./out/com/blahcode/Main.class的目录结构输出。这对于IntelliJ IDEA尤其如此

当尝试从shell或cmd运行时,需要使用cd 到包含com作为子目录的目录

cd out
java -classpath . com.blahcode.Main

如果在编译和运行时出现以下错误之一:

NoClassDefFoundError

错误:无法找到或加载主类hello

主线程java.lang.NoClassDefFoundError中出现异常:javaTest/test/hello 错误名称:test/hello

在java.lang.ClassLoader.defineClass1Native方法中 位于java.lang.ClassLoader.defineClassUnknown Source 位于java.security.SecureClassLoader.defineClassUnknown Source 位于java.net.URLClassLoader.defineClassUnknown Source 位于java.net.URLClassLoader.access$100Unknown Source 位于java.net.URLClassLoader$1.run未知源 位于java.net.URLClassLoader$1.run未知源 位于java.security.AccessController.doPrivilegeEdNative方法 位于java.net.URLClassLoader.findClassUnknown Source 位于java.lang.ClassLoader.loadClassUnknown Source 在sun.misc.Launcher$AppClassLoader.loadClassUnknown源 位于java.lang.ClassLoader.loadClassUnknown Source 位于sun.launcher.LaunchHelper.CheckAndLoadMain未知源 -------------解决方案------------

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

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

javac -d . [FileName.java]
java [Package].[ClassName]
要运行该类,请使用以下命令:

javac -d . [FileName.java]
java [Package].[ClassName]
在类路径中找不到所需的类时,将发生无类定义异常

在编译时类:类是从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源代码放在某个文件夹中,比如NoClassDefinitionFoundExceptionDemo

现在打开一个shell,假设Java已经被正确设置

转到文件夹NoClassDefinitionFoundExceptionDemo

编译Java源文件 javac类B javac类

两个文件都已成功编译,并在与ClassA.class和ClassB.class相同的文件夹中生成类文件

现在,由于我们正在重写当前工作控制器的类路径,我们执行以下命令 java-cp。甲级 它工作成功,您将在屏幕上看到输出

现在,假设您从当前目录中删除了ClassB.class文件。 现在再次执行命令。 java-cp。ClassA现在它将以NoClassDefFoundException欢迎您。在类路径(即当前工作目录)中找不到作为类a依赖项的类B

cd out
java -classpath . com.blahcode.Main

我在这条链条上的两分钱:


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

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

使用'java-javaagent:tracer.jar[您的'java'参数]运行您的程序

它生成显示加载的类和加载该类的加载程序环境的输出。跟踪类无法解析的原因非常有用

// 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;
            }
        });
    }
}
这件事发生在我身上


对我有效的解决方案是:重新启动Android Studio。

在一个NetBeans项目上工作了好几个月后,在收到内存不足警报后不久,我突然收到了NoClassDefFoundError消息。进行干净的重建没有任何帮助,但完全关闭NetBeans并重新打开项目时没有错误报告。

我使用Android studio进行Android开发时也遇到了同样的问题。提供的解决方案是通用的,至少对我没有帮助

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

修改设置如下:

偏好→ 构建、执行、部署→ 快跑→ *取消选中第一个选项

通过此更改,我可以启动并运行。

Java中的NoClassDefFoundError:

定义:

如果类在编译时存在,但在运行时java类路径中不可用,则会出现NoClassDefFoundError。通常,当您得到NoClassDefFoundError时,您会在日志中看到以下行: 主线程java.lang.NoClassDefFoundError中出现异常

可能的原因:

该类在Java类路径中不可用

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

任何启动脚本都将覆盖Classpath环境变量

因为NoClassDefFoundError是java.lang.LinkageError的一个子类,所以如果像本机库这样的依赖项之一不可用,它也可能出现

检查日志文件中的java.lang.ExceptionInInitializerError。诺卡斯德福海尔酒店 或者由于静态初始化失败是很常见的

如果您在J2EE环境中工作,那么类在多个类加载器之间的可见性也可能导致java.lang.NoClassDefFoundError,请参阅示例和场景部分以获取详细讨论

可能的决议:

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

应用程序的classpath是正确的,但是classpath环境变量在应用程序执行之前被重写

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

资源:


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

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

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

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


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

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

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

然后在主线程中调用类的field方法,就会得到NoClassDefFoundError

以下是测试代码:

public class MyClass{
       private static  Handler mHandler = new Handler();
       public static int num = 0;
}
在主活动的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);
}

如果您使用的模块不止一个,您应该

dexOptions {
    preDexLibraries = false
}

在您的生成文件中。

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

-libraryJars path.to.a.missing.jar.library

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

请注意,来自ProGuard的错误消息实际上并不符合标准,因为它们很容易与JAR文件根本不存在时收到的类似消息混淆。只有在最底层才会有一点ProGuard陷入困境的迹象。因此,开始搜索传统的类路径错误等是非常合乎逻辑的,但这将是徒劳的


显然,NoClassDefFound异常将是运行时的结果,例如,生成的可执行JAR文件是基于缺少ProGuard一致性而构建的。有人称之为地狱。我今天遇到了这个问题。我有一个Android项目,启用multidex后,该项目将不再启动

原因是我忘了调用特定的multidex方法,该方法应该添加到应用程序类中,并在调用其他方法之前进行调用

 MultiDex.install(this);
按照本教程正确启用multidex

您应该将这些行添加到应用程序类中

 @Override
  protected void attachBaseContext(Context base) {
     super.attachBaseContext(base);
     MultiDex.install(this);
  }
我使用,所以我可以在Tomcat上实时调试。我收到NoClassFoundError,因为我在Tomcat的元数据中为Eclipse workspace=>Class中的bin目录添加了一个同步条目,但我还没有为Eclipse=>extlib目录添加文件夹同步


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

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

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


该问题是由未自动更新的Bundle Activator引起的。手动更新新插件中MANIFEST.MF下的Bundle Activator已修复我的问题。

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

// To support MultiDex
implementation 'com.android.support:multidex:1.0.1'
因此,您的解决方案只是从多索引应用程序扩展而不是 应用程序:

public class MyApp extends MultiDexApplication {

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

我是如何发现这个问题的?因为我使用Selenium原生Firefox驱动程序运行我的项目,并且我的应用程序中包含一个旧版本的Firefox。然后我意识到问题在于浏览器和驱动程序之间的不兼容。

不要在模块外使用测试类 我并没有一个解决方案,只是编译时呈现的另一种风格,在运行时不存在

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


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

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

例如:

错误消息:

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

<dependency>
    <groupId>com.abc.def</groupId>
    <artifactId>foo</artifactId>
    <scope>test</scope>
</dependency>

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

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

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

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

distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-bin.zip
对于或用户

这可能是由您使用的Java版本引起的。对于Meteor和Cordova,现在坚持使用版本8

检查可用的Java版本/usr/libexec/Java_home-V,并查找Java版本8的路径名

设置Java版本8的路径 导出JAVA_HOME=/Library/JAVA/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/HOME

检查是否完成 echo$JAVA_主页

继续并继续编码。

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

Java 11+Eclipse解决方案:

如果您在Eclipse项目中没有使用module-info.java,并且您手动添加了JAR文件,而不是使用/,那么这个解决方案是适合您的

右键单击项目→ 构建路径→ 配置生成路径→ “库”选项卡 从modulepath中删除有问题的JAR文件 将JAR文件添加到类路径 更多信息请参阅
.

如果要从JAR文件启动类,请确保从JAR完整路径开始。例如,如果清单中未指定主类:

java -classpath "./dialer.jar" com.company.dialer.DialerServer
如果存在任何依赖关系,比如对其他JAR文件的依赖关系,您可以解决这种依赖关系

或者通过向类路径中的每个JAR文件添加这样的JAR文件的完整路径。例如 或者通过向清单中添加依赖项JAR文件来编辑JAR清单。这样的清单文件可能如下所示: 或者,如果您是一名拥有源代码的开发人员,您可以使用Maven通过添加到*.pom文件为您准备清单:
看看你的主要类,它不是在一个包你会有包图形;在顶端。图形是包结构的头部吗?Square顶部是否有package graphics.shapes?您列出了.java文件的位置,但由于您得到的是运行时问题,因此您真正感兴趣的是.class文件的位置以及它们是否在类路径上。如何执行主类?只需在eclipse中按Shift+ctrl+o组合键来组织导入,确保键入的类名正确。我之所以会出现这个错误,是因为我没有用大写字母开头类名。在IntelliJ IDEA中,有时在主要重构之后会出现这种情况。右键单击您的项目并选择->编译模块,然后重新启动项目,它应该会再次工作。在我的例子中,我编译了一个类,他们将其移动到一个名为app的目录中。我不得不添加一行程序包;在我将其移动到子目录应用程序之前重新编译。除了上面列出的3之外,类加载器也可能导致此类错误,基本上是ClassNotFoundException,在这种情况下,类可能出现在类路径中,但尝试从不同的类加载器加载2和3是特定于类加载器的。根据javadoc,异常仅用于原因1。我已经测试了案例2和案例3,它不是NoClassDefFoundError,而是ExceptionInInitializeError案例2.Class文件定位,但初始化静态变量时引发异常案例3.Class文件定位,初始化静态变量时引发异常blocks@Michael,此链接表示,在这种情况下,stacktrace也会显示NoClassDefFoundError:这取决于您请求的上下文。如何在运行时通过try/catch处理此问题?此答案与您编写它的方式不同。正确的会
be:此错误的一个可能原因是。。。。但可能还有其他原因导致出现此错误,例如在运行时使用类加载器加载JAR文件时。这在一定程度上是正确的,但它更复杂。1您可以在类路径中使用相对路径,但它们必须可由JVM解析。。。相对于JVM的当前目录。这使得它们很脆弱。2在设置classpath环境变量时,可以使用~和其他shell元字符,但前提是设置变量时使用的机制将它们扩展为实际路径名。如果您使用的是bash,则可能会得到不同的结果。例如,查看在命令行上键入echo~:~时得到的结果。第一个~被扩展,但第二个不是。在javac中,命令完成了这个任务,创建包的文件夹结构,而不是将所有的.class文件放在根目录中,谢谢!我之所以读这篇文章,是因为我在尝试在Android上运行单元测试时遇到了一个错误。在我的例子中,NoClassDefFoundError是由于测试中缺少依赖项而发生的。我需要考虑依赖注入来防止类似这样的错误。谢谢你详尽的回答。rpm是什么?是否与上的包管理相关?还是别的什么?
Manifest-Version: 1.0
Class-Path: phone.jar anotherlib.jar
Build-Jdk-Spec: 1.8
Main-Class: com.company.dialer.DialerServer
<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>
java -classpath ./libs/phone.jar:./libs/anotherlib.jar:./dialer.jar
com.company.dialer.DialerServer