运行Java应用程序时出现NoClassDefFoundError
。 通常是什么原因造成的?
#1楼
这是说明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;
}
#2楼
我在Maven中使用Spring Framework ,并在我的项目中解决了此错误。
该类中存在运行时错误。 我正在将属性读取为整数,但是当它从属性文件读取值时,其值是两倍。
Spring并没有给我完整的堆栈跟踪信息,表明运行失败的那一行。 它只是说了NoClassDefFoundError
。 但是,当我将其作为本机Java应用程序执行(从MVC中取出)时,它给出了ExceptionInInitializerError
,这是真正的原因,也是我跟踪错误的方式。
@xli的答案使我深入了解了我的代码中可能存在的问题。
#3楼
当运行时类加载器加载的类无法访问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;
}
});
}
}
#4楼
这是我到目前为止发现的最佳解决方案 。
假设我们有一个名为org.mypackage
的包, org.mypackage
包含以下类:
- HelloWorld(主类)
- 技术支持
- 实用程序类
并且定义此软件包的文件实际存储在目录D:\\myprogram
(在Windows上)或/home/user/myprogram
(在Linux上)下。
调用Java时,我们指定要运行的应用程序的名称: org.mypackage.HelloWorld
。 但是,我们还必须告诉Java在哪里寻找定义我们程序包的文件和目录。 因此,要启动该程序,我们必须使用以下命令:
#5楼
从SRC库中删除了两个文件后,我收到了此消息,当我将它们放回时,我一直看到此错误消息。
我的解决方案是:重新启动Eclipse。 从那时起,我再也没有看到此消息:-)
#6楼
当您的代码依赖于一个类文件,并且该类文件在编译时存在但在运行时未找到时,会导致这种情况。 在构建时间和运行时类路径中寻找差异。
#7楼
我发现有时使用在运行时发现的类的不兼容版本编译代码时,有时会出现NoClassDefFound错误。 我记得的特定实例与apache轴库有关。 我的运行时类路径上实际上有2个版本,并且它选择的是过时且不兼容的版本,而不是正确的版本,从而导致NoClassDefFound错误。 这是在命令行应用程序中,我在其中使用与此类似的命令。
set classpath=%classpath%;axis.jar
我能够使用以下命令获取正确的版本:
set classpath=axis.jar;%classpath%;
#8楼
确保这在module:app
和module:lib
匹配:
android {
compileSdkVersion 23
buildToolsVersion '22.0.1'
packagingOptions {
}
defaultConfig {
minSdkVersion 17
targetSdkVersion 23
versionCode 11
versionName "2.1"
}
#9楼
我遇到了同样的问题,而且库存很多小时。
我找到了解决方案。 在我的情况下,因此定义了静态方法。 JVM无法创建该类的另一个对象。
例如,
private static HttpHost proxy = new HttpHost(proxyHost, Integer.valueOf(proxyPort), "http");
#10楼
以下技术对我有很多帮助:
System.out.println(TheNoDefFoundClass.class.getProtectionDomain().getCodeSource().getLocation());
其中,TheNoDefFoundClass是由于对程序使用的同一个库的较旧版本的偏好而可能“丢失”的类。 这种情况最常发生在以下情况中:将客户端软件部署到一个占主导地位的容器中,并带有其自己的类加载器和成千上万个最流行的lib的古代版本。
#11楼
Java中的NoClassDefFoundError
定义:
Java虚拟机无法在运行时找到编译时可用的特定类。
如果一个类在编译期间存在,但在运行时在java classpath中不可用。
例子:
- 该类不在Classpath中,没有确定的了解方法,但是很多时候您只需要看一下即可打印System.getproperty(“ java.classpath”),它将从那里打印出类路径,您至少可以得到您的实际运行时类路径的想法。
NoClassDefFoundError的一个简单示例是类属于丢失的JAR文件,或者未将JAR添加到类路径中,或者有时有人更改了jar的名称,例如在我的一个同事中,将tibco.jar更改为tibco_v3.jar,程序是java.lang.NoClassDefFoundError失败,我想知道怎么了。
只需尝试在您认为可以使用的类路径上显式地使用-classpath选项即可运行,如果可以正常工作,则可以肯定地表明有人正在重写Java类路径。
- JAR文件的权限问题也可能导致Java中出现NoClassDefFoundError。
- XML配置上的错字也可能导致Java中的NoClassDefFoundError。
- 当在包中定义的已编译类在加载时不在同一包中时(如JApplet),它将在Java中引发NoClassDefFoundError。
可能的解决方案:
- 该类在Java Classpath中不可用。
- 如果您在J2EE环境中工作,则多个Classloader之间Class的可见性也可能导致java.lang.NoClassDefFoundError,请参阅示例和场景一节以获取详细讨论。
- 在日志文件中检查java.lang.ExceptionInInitializerError。 由于静态初始化失败而导致的NoClassDefFoundError非常普遍。
- 由于NoClassDefFoundError是java.lang.LinkageError的子类,因此如果其中一个依赖项(如本机库)可能不可用,它也可能出现。
- 任何启动脚本都将覆盖Classpath环境变量。
- 您可能正在使用jar命令运行程序,并且清单文件的ClassPath属性中未定义类。
资源:
java.lang.NoClassDefFoundError问题模式
#12楼
如果您已生成代码(EMF等),则可能有太多静态初始化程序占用所有堆栈空间。
请参阅堆栈溢出问题。 如何增加Java堆栈大小? 。
#13楼
如果有人因为java.lang.NoClassDefFoundError: org/apache/log4j/Logger
错误而来到这里,则在我的情况下是由于我使用log4j 2而产生的(但我没有添加它随附的所有文件),还有一些依赖库使用log4j1。解决方案是添加Log4j 1.x桥:log4j 2附带的jar log4j-1.2-api-<version>.jar
。更多有关log4j 2 迁移的信息 。
#14楼
同一项目的两个不同的结帐副本
就我而言,问题是Eclipse无法区分同一项目的两个不同副本。 我有一个锁定在主干(SVN版本控制)上,而另一个则一次在一个分支中工作。 我尝试将工作副本中的一个更改作为JUnit测试用例进行了测试,其中包括将一个私有内部类本身提取为一个公共类,并且在工作时,我打开了该项目的另一个副本以查看其他内容。需要更改的部分代码。 在某个时刻, NoClassDefFoundError
弹出来,抱怨私有内部类不存在。 双击堆栈跟踪将我带到错误的项目副本中的源文件。
关闭项目的主干副本并再次运行测试用例解决了这个问题。
#15楼
Java无法在运行时中找到类A。 A类在其他工作区的Maven项目ArtClient中。 因此,我将ArtClient导入了我的Eclipse项目。 我的两个项目使用ArtClient作为依赖项。 我将库参考更改为这些项目的项目参考(构建路径->配置构建路径)。
问题消失了。
#16楼
我通过禁用所有模块的preDexLibraries解决了我的问题:
dexOptions {
preDexLibraries false
...
#17楼
此错误可能是由于未经检查的Java版本要求引起的。
就我而言,通过使用SDKMAN从Java 9切换到Java 8,在构建一个备受瞩目的开源项目时,我能够解决此错误! 。
sdk list java
sdk install java 8u152-zulu
sdk use java 8u152-zulu
然后按照以下说明进行全新安装。
当使用Maven作为构建工具,它有时是有益的-通常喜人,做一个干净的 “安装”构建与测试禁用 。
mvn clean install -DskipTests
现在, 所有内容均已构建并安装,您可以继续运行测试。
mvn test
#18楼
当静态初始化程序尝试加载运行时不可用的资源包时,例如,受影响的类尝试从META-INF
目录中加载但不存在的属性文件,也会发生NoClassDefFoundError
。 如果您没有捕获NoClassDefFoundError
,有时您将看不到完整的堆栈跟踪信息。 为了克服这个问题,您可以为Throwable
临时使用catch
子句:
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);
}
#19楼
在以下情况中,您可能会看到很多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
。
当您在UNIT TESTS中看到NoClassDefFoundErrors
时,这尤其重要。
在某种程度上,您是“共享”测试之间的static
块执行,但是初始ExceptionInInitializerError
只是在一个测试用例中。 第一个使用有问题的Example
类。 使用Example
类的其他测试用例只会抛出NoClassDefFoundErrors
。
#20楼
当我没有在项目的Java Build Path的“ Order and Export”选项卡上导出类时,出现NoClassDefFound错误。 确保在添加到项目的构建路径中的所有依赖项的“订单和导出”选项卡中打上对勾。 请参阅Eclipse警告:XXXXXXXXXXX.jar将不会导出或发布。 运行时ClassNotFoundExceptions可能会导致 。
#21楼
也可能是因为您从IDE复制具有特定程序包名称的代码文件,并想尝试使用终端运行它。 您必须首先从代码中删除程序包名称。 这发生在我身上。
#22楼
尽管这可能是由于编译时和运行时之间的类路径不匹配导致的,但不一定是正确的。
在这种情况下,请务必牢记两个或三个不同的异常:
java.lang.ClassNotFoundException
此异常表明在类路径上找不到该类。 这表明我们正在尝试加载类定义,并且该类在类路径中不存在。java.lang.NoClassDefFoundError
此异常表明JVM在其内部类定义数据结构中查找了类的定义,但未找到。 这与说无法从类路径中加载不同。 通常,这表明我们以前曾尝试从类路径中加载类,但由于某种原因而失败-现在我们正尝试再次使用该类(因此,由于上次失败,因此需要对其进行加载),但是我们甚至不打算尝试加载它,因为我们无法提前加载它(并且合理地怀疑我们会再次失败)。 较早的故障可能是ClassNotFoundException或ExceptionInInitializerError(指示静态初始化块中的故障)或许多其他问题。 关键是,NoClassDefFoundError不一定是类路径问题。
#23楼
当我在项目中添加另一个模块的Maven依赖项时出现此错误,该问题最终通过在程序的JVM选项中添加-Xss2m
来解决(自JDK5.0起默认为1兆字节)。 可以认为程序没有足够的堆栈来加载类。