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

我已经尝试了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的,但它们有类似的概念。

1510589 次浏览

NoClassDefFoundError意味着类存在于Compile time的类路径中,但它不存在于Runtime的类路径中。

如果您正在使用Eclipse,请确保在.classpath文件中有shapeslinepointsspaceobjects作为条目。

java.lang.NoClassDefFoundError

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

编译代码后,程序中的每个类都有.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的发生有多种原因,比如:

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

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

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

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

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

  • 编译时类和运行时类是不同的,例如基类是用子类的类名加载的 forname(“classname") 例如:两个类,A和B(扩展A)。Code有
    A a = Class.forName("B").newInstance(); < / >

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

当试图从shell或cmd运行时,你需要cd到包含com作为子目录的目录。

cd out
java -classpath . com.blahcode.Main

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

  • < p > NoClassDefFoundError

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

  • 线程“main”异常;java.lang.NoClassDefFoundError: javaTest /测试/你好 (错误的名字: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)
    

-------------------------- __ ABC0 -----------------------

问题主要出在包装组织上。您应该根据源代码中的包分类在文件夹中适当地安排类。

在编译过程中,使用这个命令:

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源代码被放置在某个文件夹中,例如“NoClassDefinationFoundExceptionDemo"

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

  1. 进入文件夹“NoClassDefinationFoundExceptionDemo"

  2. 编译Java源文件 javac ClassB javac ClassA < / p >

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

  4. 现在,由于我们要将ClassPath覆盖到当前工作指令,我们执行以下命令 Java -cp。ClassA 它成功地工作了,您将在屏幕上看到输出

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

我的观点是:

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

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

使用'java -javaagent:trace .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;
}
});
}
}

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

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

它发生在我Android工作室

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

在NetBeans项目工作了好几个月之后,我突然收到了NoClassDefFoundError消息,就在我收到“低内存”的消息后不久。警报。进行Clean重建并没有帮助,但是完全关闭NetBeans并重新启动项目时没有出现错误报告。

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

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

修改如下:

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

有了这个改变,我就可以开始工作了。

Java中的NoClassDefFoundError:

定义:

如果一个类在编译时存在,但在运行时java类路径中不可用,则会出现NoClassDefFoundError。通常,当你获得NoClassDefFoundError时,你会在log中看到下面这行: java.lang.NoClassDefFoundError

可能的原因:

  1. 这个类在Java Classpath中不可用。

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

  3. 任何启动脚本都重写Classpath环境变量。

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

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

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

可能的决议:

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

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

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

资源:

3种解决Java .lang. noclassdeffounderror的方法

java.lang。NoClassDefFoundError -如何解决没有类Def发现错误 < / > < / p >

这个答案是特定于发生在服务中的java.lang.NoClassDefFoundError:

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

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

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

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

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

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

如果您正在使用一个以上的模块,您应该有

dexOptions {
preDexLibraries = false
}

在构建文件中。

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

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

这就解释了为什么在JAR文件存在的情况下,编译和运行工作正常,而清理和构建则失败。记住要在ProGuard设置中定义新添加的JAR库!

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

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

我今天遇到了这个问题。我有一个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);
}

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

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

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

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

该问题是由尚未自动更新的包激活器引起的。手动更新新插件中的清单。曼氏金融下的Bundle-Activator已经解决了我的问题。

如果你最近在Android Studio中添加了这样的multidex支持:

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

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

public class MyApp extends MultiDexApplication {

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

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

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

不要在模块之外使用测试类

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

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

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

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

例子:

错误信息:

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

砰的一声内容:

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

我在Git分支更改后得到了这个错误。对于Eclipse的特定情况,.settings目录中缺少org.eclipse.wst.common.component文件. xml文件的行。如下图所示。

使用Maven安装恢复项目依赖关系会有所帮助。

Enter image description here

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

如果您正在使用JDK14,请尝试:

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

对于流星科尔多瓦用户,

这可能是由您使用的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 < / p >

  3. 检查是否完成 echo $JAVA_HOME < / p >

继续编写代码。

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

Java 11 + Eclipse解决方案:

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

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

更多信息 在Eclipse中,modulepath和classpath之间的区别是什么? < / em >。

如果你正在“开始”;一个JAR文件中的类,请确保从JAR完整路径开始。例如,(如果你的"main class"舱单上没有指明):

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

我删除了文件夹“build "和"out", IDE重新构建该文件夹与更新的内容文件。

如果您正在使用Maven,这可能是由于pom.xml中依赖项的范围,如果它们被设置为“提供”,请尝试将其更改为“编译”。

如果使用Eclipse,请检查运行配置/依赖项。我在使用Java构建路径/库中包含的外部jar文件时遇到了这个问题,但不知为何没有在运行配置/依赖项中列出。