Java NoClassDefFoundError错误完全指南:原因、排查与解决方案

当在类路径中找不到所需的类时,会出现java.lang.NoClassDefFoundError运行时错误,因此JVM无法将该类加载到内存中。

java.lang.NoClassDefFoundError – 类定义未找到错误

java.lang.NoClassDefFoundError
  • NoClassDefFoundError是一个运行时错误,因此超出了我们应用程序的预期和恢复范围。
  • java.lang.NoClassDefFoundError是一个运行时错误,它永远不会在编译时出现。
  • 调试NoClassDefFoundError非常容易,因为它明确指出JVM无法找到所需的类,因此请检查类路径配置以确保没有遗漏所需的类。

找不到类定义错误的类图

java lang NoClassDefFoundError Class Diagram

Java.lang.NoClassDefFoundError的原因是什么?

首先,让我们尝试复制一个运行时出现NoClassDefFoundError的场景。假设我们有以下的Java类。

public class Data {

	private int id;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}
	
}

请注意,上述类不依赖于任何其他自定义Java类,它只使用了Java内置类。让我们创建另一个类,在同一目录中使用Data类。

public class DataTest {

	public static void main(String[] args) {
		Data data = new Data();
		data.setId(10);
		System.out.println("Data Id = "+data.getId());
	}

}

现在让我们编译DataTest类,然后执行它,就像下面这样。

scdev:temp scdev$ ls
Data.java	DataTest.java
scdev:temp scdev$ javac DataTest.java 
scdev:temp scdev$ ls 
Data.class	Data.java	DataTest.class	DataTest.java
scdev:temp scdev$ java DataTest
Data Id = 10
scdev:temp scdev$

到目前为止一切都很好,现在让我们把Data类文件移到其他地方,然后尝试执行DataTest类。我们不会再次编译它,因为那样会导致编译错误。

scdev:temp scdev$ mv Data.java Data.class ../
scdev:temp scdev$ ls
DataTest.class	DataTest.java
scdev:temp scdev$ java DataTest
Exception in thread "main" java.lang.NoClassDefFoundError: Data
	at DataTest.main(DataTest.java:5)
Caused by: java.lang.ClassNotFoundException: Data
	at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	... 1 more
scdev:temp scdev$ 
java.lang.NoClassDefFoundError example

如何解决java.lang.NoClassDefFoundError错误?

通过以上示例,我们可以明确地确定此错误的唯一原因是在编译时期所需的类是可用的,但在运行时却不可用。您可以通过检查以下内容来修复NoClassDefFoundError错误:

  • 检查异常堆栈跟踪,以确切知道哪个类抛出了错误以及哪个类是Java找不到的类。
  • 下一步是查找类路径配置,有时我们在Eclipse或其他环境中编译类,而在其他环境中运行,可能会遗漏类路径配置。例如,我可以通过将包含Data类的目录添加到类路径中来轻松解决上述问题,如下所示。
    scdev:temp scdev$ java -classpath .:.. DataTest
    Data Id = 10
    scdev:temp请记住,之前我已将Data类移动到上一个目录。
  • 大多数情况下,NoClassDefFoundError出现在作为Web应用程序或Web服务在某个服务器上运行的应用程序中,在这种情况下,请检查所需的jar文件是否是WAR文件的一部分。例如,下面的Maven配置在生成WAR文件时不会打包jar文件。

    javax.servlet
    servlet-api
    3.0.1
    provided
    但是我们需要它来创建基于servlet的Web应用程序,通常这个jar文件总是Tomcat或任何其他应用程序服务器的一部分。

这就是对java.lang.NoClassDefFoundError的简要介绍,希望当你遇到这个错误时能够获取足够的想法,并且轻松地修复它。参考资料:API文档,Java中的异常处理。

bannerAds