当我运行Java应用程序时,我得到了一个NoClassDefFoundError。造成这种情况的典型原因是什么?


当前回答

这是由于您的代码所依赖的类文件在编译时存在,但在运行时没有找到。寻找构建时和运行时类路径的差异。

其他回答

Java ClassNotFoundException vs NoClassDefFoundError

黑ClassLoader铝

静态与动态类加载

静态(隐式)类加载——引用、实例化或继承的结果。

MyClass myClass = new MyClass();

动态(显式)类加载是class . forname (), loadClass(), findSystemClass()的结果

MyClass myClass = (MyClass) Class.forName("MyClass").newInstance();

每个类都有一个ClassLoader,它使用loadClass(字符串名);这就是为什么

explicit class loader uses implicit class loader

NoClassDefFoundError是显式类装入器的一部分。Error是为了保证在编译期间出现这个类,但现在(在运行时)它不存在。

ClassNotFoundException是隐式类装入器的一部分。Exception对于可以额外使用的场景(例如反射)具有弹性。

我发现,当使用运行时发现的不兼容的类版本编译代码时,有时会得到NoClassDefFound错误。我记得的具体实例是apache axis库。在我的运行时类路径上实际上有2个版本,它正在挑选过时和不兼容的版本,而不是正确的版本,导致NoClassDefFound错误。这是在一个命令行应用程序中,我正在使用类似的命令。

set classpath=%classpath%;axis.jar

我能够让它拿起正确的版本使用:

set classpath=axis.jar;%classpath%;

如果您有生成代码(EMF等),可能会有太多的静态初始化器,这会占用所有的堆栈空间。

参见堆栈溢出问题如何增加Java堆栈大小?。

每个人都在这里谈论一些Java配置的东西,JVM的问题等,在我的情况下,错误与这些主题完全无关,有一个非常琐碎和容易解决的原因:我在我的控制器(Spring Boot应用程序)的端点有一个错误的注释。

当静态初始化器试图加载一个在运行时不可用的资源包时,也会发生NoClassDefFoundError,例如受影响的类试图从META-INF目录加载一个属性文件,但不存在。如果你没有捕获NoClassDefFoundError,有时你将无法看到完整的堆栈跟踪;为了克服这个问题,你可以临时为Throwable使用一个catch子句:

try {
    // Statement(s) that cause(s) the affected class to be loaded
} catch (Throwable t) {
    Logger.getLogger("<logger-name>").info("Loading my class went wrong", t);
}