Answers:
这是由于存在代码所依赖的类文件,并且该类文件在编译时存在而在运行时未找到。在构建时间和运行时类路径中寻找差异。
尽管这可能是由于编译时和运行时之间的类路径不匹配导致的,但不一定是正确的。
在这种情况下,请务必牢记两个或三个不同的异常:
java.lang.ClassNotFoundException
此异常表明在类路径上找不到该类。这表明我们正在尝试加载类定义,并且该类在类路径中不存在。
java.lang.NoClassDefFoundError
此异常表明JVM在其内部类定义数据结构中查找了类的定义,但未找到。这与说无法从类路径中加载不同。通常,这表明我们以前曾尝试从类路径中加载类,但由于某种原因而失败-现在我们正尝试再次使用该类(因此,由于上次失败,因此需要加载它),但是我们甚至不打算尝试加载它,因为我们无法更早加载它(并且合理地怀疑我们会再次失败)。较早的故障可能是ClassNotFoundException或ExceptionInInitializerError(指示静态初始化块中的故障)或许多其他问题。关键是,NoClassDefFoundError不一定是类路径问题。
Error: Could not find or load main class
,它将分类为哪个错误类别?
这是说明的代码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()
调用时,您会收到一个由ArithmeticException引起的ExceptionInInitializerError。第二次调用时,new SimpleCalculator()
您会得到一个NoClassDefFoundError,其纯度与其他任何类一样。关键是,由于运行时不在类路径上的SimpleCalculator.class以外的原因,您可以获得NoClassDefFoundError。
Java中的NoClassDefFoundError
定义:
Java虚拟机无法在运行时找到编译时可用的特定类。
如果一个类在编译时存在,但在运行时在java classpath中不可用。
例子:
NoClassDefFoundError的一个简单示例是类属于丢失的JAR文件,或者未将JAR添加到类路径中,或者有时有人更改了jar的名称,例如在我的一个同事中,将tibco.jar更改为tibco_v3.jar,程序是java.lang.NoClassDefFoundError失败,我想知道怎么了。
只需尝试在您认为可以使用的类路径上显式地使用-classpath选项即可运行,如果可以正常运行,那么这肯定是有人重写Java类路径的简短标志。
可能的解决方案:
资源:
我发现有时使用在运行时找到的类的不兼容版本编译代码时,有时会出现NoClassDefFound错误。我记得的特定实例与apache轴库有关。我的运行时类路径上实际上有2个版本,并且它选择了过时且不兼容的版本,而不是正确的版本,从而导致NoClassDefFound错误。这是在命令行应用程序中,我在其中使用与此类似的命令。
set classpath=%classpath%;axis.jar
我能够使用以下命令获取正确的版本:
set classpath=axis.jar;%classpath%;
我在Maven中使用Spring Framework,并在我的项目中解决了此错误。
该类中存在运行时错误。我正在将属性读取为整数,但是当它从属性文件读取值时,其值是两倍。
Spring没有给我完整的堆栈跟踪信息,表明运行时在哪一行失败。简单地说NoClassDefFoundError
。但是当我将其作为本机Java应用程序(从MVC中取出)执行时,它给了ExceptionInInitializerError
了真正的原因以及跟踪错误的方式。
@xli的答案使我深入了解了我的代码中可能存在的问题。
NoClassDefFoundError
实际上是由引起的ExceptionInInitalizerError
,这是由引起的DateTimeParseException
)。这有点误导,不是吗?我知道他们可能有这样做的理由,但是至少要有一个小提示真是太好了,这NoClassDefFoundError
是另一个例外的结果,而无需推断出它。仅ExceptionInInitializerError
再次抛出将更加清楚。有时两者之间的联系可能并不那么明显。
当运行时类加载器加载的类无法访问Java rootloader已加载的类时,出现NoClassFoundError。由于不同的类加载器位于不同的安全域中(根据Java),因此jvm不允许在运行时加载器地址空间中解析由根加载器加载的类。
使用“ java -javaagent:tracer.jar [您的Java插件]”运行程序
它产生的输出显示已加载的类,以及加载该类的加载器env。跟踪为什么无法解析类非常有用。
// 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;
}
});
}
}
您可能会看到很多有趣的情况NoClassDefFoundErrors
是,当您:
throw
一个RuntimeException
在static
你的类的块Example
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
}
}
NoClassDefError
将与ExceptionInInitializerError
从静态块一起抛出RuntimeException
。
当您NoClassDefFoundErrors
在UNIT TESTS中看到时,这尤其重要。
在某种程度上,您是“共享” static
测试之间的块执行,但是最初ExceptionInInitializerError
只是在一个测试用例中。第一个使用有问题的Example
类。使用Example
该类的其他测试用例只会抛出NoClassDefFoundErrors
。
以下技术对我有很多帮助:
System.out.println(TheNoDefFoundClass.class.getProtectionDomain().getCodeSource().getLocation());
其中,TheNoDefFoundClass是由于对程序使用的同一个库的较旧版本的偏好而可能“丢失”的类。这种情况最常发生在以下情况中:将客户端软件部署到一个占主导地位的容器中,并带有其自己的类加载器和成千上万个最流行的lib的古代版本。
如果您已生成代码(EMF等),则可能有太多静态初始化程序占用所有堆栈空间。
请参阅堆栈溢出问题。如何增加Java堆栈大小?。
NoClassDefFoundError
当静态初始化程序尝试加载运行时不可用的资源束时,也会发生这种情况,例如,受影响的类试图从META-INF
目录加载但不在目录中的属性文件。如果您没有抓住NoClassDefFoundError
,有时您将看不到完整的堆栈跟踪信息。为了克服这个问题,您可以暂时使用以下catch
子句Throwable
:
try {
// Statement(s) that cause the affected class to be loaded
} catch (Throwable t) {
Logger.getLogger("<logger-name>").info("Loading my class went wrong", t);
}
for example a properties file that the affected class tries to load from the META-INF directory
。这实际上发生在我身上,我能够NoClassDefFoundError
通过添加缺少的属性文件来解决。我之所以添加此答案,恰恰是因为在上述情况下不会出现此错误。
static
初始化中加载资源文件,则会触发未检查的异常并导致类初始化。失败。从静态初始化传播的任何未经检查的异常都可以做到这一点。
static
初始化失败而引起的),我将很想看到一个演示该行为的实际示例(即MCVE)。
当我将另一个模块的Maven依赖项添加到我的项目中时,出现了此错误,该问题最终通过添加-Xss2m
到程序的JVM选项中解决了(自JDK5.0起默认为1兆字节)。可以认为程序没有足够的堆栈来加载类。
当我没有在项目的Java Build Path的“ Order and Export”选项卡上导出类时,出现NoClassDefFound错误。确保在添加到项目的构建路径中的所有依赖项的“订购和出口”选项卡中打上对勾。请参阅Eclipse警告:XXXXXXXXXXX.jar将不会导出或发布。运行时ClassNotFoundExceptions可能会导致。
这里的每个人都在谈论一些Java配置问题,JVM问题等,在我的情况下,该错误与这些主题完全无关,并且具有非常简单且易于解决的原因:我在Controller的端点上标注了错误的注释( Spring Boot应用程序)。
我在使用Liberty服务器的JavaEE中遇到了一个NoClassDefFoundError有趣的问题。我正在使用IMS资源适配器,而我的server.xml已经具有imsudbJXA.rar的资源适配器。当我为imsudbXA.rar添加新适配器时,对于DLIException,IMSConnectionSpec或SQLInteractionSpec的实例对象,我将开始收到此错误。我不知道为什么,但是我通过仅使用imsudbXA.rar为我的工作创建了新的server.xml来解决了该问题。我确定在server.xml中使用多个资源适配器是可以的,但是我没有时间去研究它。
从SRC库中删除了两个文件后,我收到了此消息,当我将它们放回时,我一直看到此错误消息。
我的解决方案是:重新启动Eclipse。从那时起,我再也没有看到此消息:-)