当我运行我的Java应用程序时,出现了NoClassDefFoundError
。通常这是什么原因导致的?
当我运行我的Java应用程序时,出现了NoClassDefFoundError
。通常这是什么原因导致的?
虽然这可能是由于编译时和运行时之间的类路径不匹配,但并不一定如此。
在这种情况下,我们在头脑中要清晰区分两到三个不同的异常:
java.lang.ClassNotFoundException
该异常表示未在类路径上找到该类。这意味着我们试图加载类定义,但该类不存在于类路径上。
java.lang.NoClassDefFoundError
该异常表示JVM在其内部类定义数据结构中查找一个类的定义,但未找到它。这与说它无法从类路径加载不同。通常,这表明我们之前尝试从类路径加载类,但由于某些原因失败了 - 现在我们再次尝试使用该类(因此需要加载它,因为上次加载失败了),但我们甚至不会尝试加载它,因为我们之前加载失败(并且合理地怀疑我们将再次加载失败)。先前的失败可能是ClassNotFoundException或ExceptionInInitializerError(指静态初始化块中的失败)或任何其他问题。重点是,NoClassDefFoundError并不一定是类路径问题。
ClassCircularityError
和ClassFormatError
:http://docs.oracle.com/javase/specs/jls/se5.0/html/execution.html#12.2.1 - Pacerier当您的代码依赖的类文件在编译时存在,但在运行时未找到时,会发生这种情况。请查看构建时间和运行时类路径之间的差异。
以下是代码,用于说明java.lang.NoClassDefFoundError
错误。请参见Jared的答案以获取详细解释。
NoClassDefFoundErrorDemo.java
public class NoClassDefFoundErrorDemo {
public static void main(String[] args) {
try {
// The following line would throw ExceptionInInitializerError
SimpleCalculator calculator1 = new SimpleCalculator();
} catch (Throwable t) {
System.out.println(t);
}
// The following line would cause NoClassDefFoundError
SimpleCalculator calculator2 = new SimpleCalculator();
}
}
SimpleCalculator.java
public class SimpleCalculator {
static int undefined = 1 / 0;
}
SimpleCalculator
的初始化失败。有人有关于此行为的官方文档参考吗? - ᴠɪɴᴄᴇɴᴛnew SimpleCalculator()
时,会出现一个具有算术异常原因的ExceptionInInitializerError。第二次调用new SimpleCalculator()
时,您会像其他任何情况一样得到一个非常“纯”的NoClassDefFoundError。关键在于,您可能会由于运行时存在SimpleCalculator.class之外的原因而获得NoClassDefFoundError。 - harperskaJava中的NoClassDefFoundError错误
定义:
Java虚拟机在运行时无法找到编译时可用的某个类。
如果一个类在编译时存在,但在Java类路径在运行时不可用。
示例:
NoClassDefFoundError的一个简单例子是类属于丢失的JAR文件或JAR未添加到classpath中,有时JAR的名称已被某人更改,例如在我的情况下,我的一个同事将tibco.jar更改为tibco_v3.jar,程序失败并显示java.lang.NoClassDefFoundError,我想知道出了什么问题。
尝试使用显式-classpath选项运行您认为会起作用的classpath,如果它可以工作,则这是某人覆盖java classpath的明确迹象。
可能的解决方案:
资源:
我发现有时候在运行时,编译的代码与类的不兼容版本产生NoClassDefFound错误。我回忆起来的具体实例是在使用Apache Axis库时出现的。我的运行时类路径上实际上有两个版本,它选择了过时和不兼容的版本而不是正确的版本,导致了NoClassDefFound错误。这是在一个命令行应用程序中,我使用了类似于这样的命令。
set classpath=%classpath%;axis.jar
通过使用以下方法,我成功让它选择正确的版本:
set classpath=axis.jar;%classpath%;
这是我目前找到的最佳解决方案。
假设我们有一个名为org.mypackage
的包,其中包含以下类:
并且定义此包的文件在物理上存储在目录D:\myprogram
(Windows上)或/home/user/myprogram
(Linux上)下。
当我们调用Java时,我们指定要运行的应用程序的名称:org.mypackage.HelloWorld
。但是我们还必须告诉Java在哪里查找定义我们的包的文件和目录。因此,要启动程序,我们必须使用以下命令:
NoClassDefFoundErrors
:
Example
的static
块中抛出RuntimeException
Example
的实例static class Example {
static {
thisThrowsRuntimeException();
}
}
static class OuterClazz {
OuterClazz() {
try {
new Example();
} catch (Throwable ignored) { //simulating catching RuntimeException from static block
// DO NOT DO THIS IN PRODUCTION CODE, THIS IS JUST AN EXAMPLE in StackOverflow
}
new Example(); //this throws NoClassDefFoundError
}
}
当静态代码块RuntimeException
中出现NoClassDefError
时,会抛出ExceptionInInitializerError
异常。
在单元测试中出现NoClassDefFoundErrors
时,这种情况尤其重要。
在某种程度上,你正在在测试之间“共享”static
块的执行,但最初的ExceptionInInitializerError
将只在一个测试用例中出现。它会在使用有问题的Example
类的第一个测试用例中出现。使用Example
类的其他测试用例将只会抛出NoClassDefFoundErrors
异常。
我使用Spring Framework和Maven,并在我的项目中解决了此错误。
类中发生了运行时错误。 我正在将属性读取为整数,但当它从属性文件中读取值时,其值是双精度浮点数。
Spring没有给出完整的堆栈跟踪以指示运行时失败的代码行。
它只是说NoClassDefFoundError
。 但是,当我将其作为本机Java应用程序执行(将其取出MVC),它会产生真正的原因ExceptionInInitializerError
,这就是我追踪错误的方式。
@xli的答案让我更好地理解了我的代码可能存在的问题。
NoClassDefFoundError
实际上是由ExceptionInInitializerError
引起的,而这又是由DateTimeParseException
引起的)。这有点误导人,不是吗?我知道他们可能有他们的理由让它变成这样,但是至少给出一个小提示,说明NoClassDefFoundError
是另一个异常的结果,而无需推断。只是再次抛出ExceptionInInitializerError
会更清晰明了。有时两者之间的联系可能并不那么明显。 - Bartłomiej Zieliński使用“java-javaagent:tracer.jar [YOUR java ARGS]”运行程序
它会产生输出,显示加载的类和加载该类的加载器环境。这对追踪无法解决类的原因非常有帮助。
// 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;
}
});
}
}
System.out.println(TheNoDefFoundClass.class.getProtectionDomain().getCodeSource().getLocation());
其中,TheNoDefFoundClass 是一个类,可能会因为程序使用旧版本的同一库而“丢失”。这种情况最常见于客户端软件部署到支持自己的类加载器和大量古老版本的流行库的主流容器中。