当我运行我的Java应用程序时,我得到了一个NoClassDefFoundError
。这通常是什么原因?
这是因为当您的代码依赖于类文件并且它在编译时出现但在运行时未找到时。查找构建时和运行时类路径的差异。
如果您有生成代码(EMF等),可能会有太多静态初始化程序占用所有堆栈空间。
请参阅Stack Overflow问题How to increase the Java stack size?。
下面的技术帮了我很多次:
System.out.println(TheNoDefFoundClass.class.getProtectionDomain().getCodeSource().getLocation());
其中TheNoDefFoundClass是由于您对程序使用的同一个库的旧版本的偏好而可能“丢失”的类。当客户端软件被部署到一个占主导地位的容器中时,最常发生这种情况,它拥有自己的类加载器和大量最流行的库的古老版本。
我通过禁用所有模块的preDexLibraries来修复我的问题:
dexOptions {
preDexLibraries false
...
当静态初始化程序尝试加载运行时不可用的资源包时,也会发生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);
}
如果有人因为java.lang.NoClassDefFoundError: org/apache/log4j/Logger
错误而来到这里,在我的情况下它是因为我使用了log4j 2(但我没有添加它附带的所有文件)而产生的,并且一些依赖库使用log4j 1.解决方案是添加Log4j 1.x网桥:与log4j一起提供的jar log4j-1.2-api-<version>.jar
2.更多信息在log4j 2 migration中。
就我而言,问题是Eclipse无法区分同一项目的两个不同副本。我有一个锁定在trunk(SVN版本控制)上,另一个一次在一个分支中工作。我尝试将工作副本中的一个更改作为JUnit测试用例,其中包括将私有内部类提取为自己的公共类,并且当它工作时,我打开项目的另一个副本来环顾其他一些需要更改的部分代码。在某些时候,NoClassDefFoundError
突然抱怨私人内部阶级不存在;双击堆栈跟踪将我带到错误的项目副本中的源文件。
关闭项目的主干副本并再次运行测试用例可以解决问题。
此错误可能是由未经检查的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
当我没有在项目的Java Build Path中的“Order and Export”选项卡上导出类时,我得到了NoClassDefFound错误。确保在添加到项目构建路径的任何依赖项的“Order and Export”选项卡中添加一个复选标记。见Eclipse warning: XXXXXXXXXXX.jar will not be exported or published. Runtime ClassNotFoundExceptions may result。
Java无法在运行时找到A类。 A类是来自不同工作空间的maven项目ArtClient。所以我将ArtClient导入我的Eclipse项目。我的两个项目是使用ArtClient作为依赖项。我将库引用更改为这些项目的引用(构建路径 - >配置构建路径)。
而问题消失了。
我有同样的问题,我有很多小时的存量。
我找到了解决方案。在我的例子中,由于这个原因定义了静态方法。 JVM无法创建该类的另一个对象。
例如,
private static HttpHost proxy = new HttpHost(proxyHost, Integer.valueOf(proxyPort), "http");
虽然这可能是由于编译时和运行时之间的类路径不匹配,但它不一定是真的。
在这种情况下,重要的是要保持两到三个不同的例外:
java.lang.ClassNotFoundException
此异常表示在类路径中找不到该类。这表明我们正在尝试加载类定义,并且类在路径上不存在。java.lang.NoClassDefFoundError
此异常表示JVM在其内部类定义数据结构中查找了类的定义但未找到它。这与说它无法从类路径加载不同。通常这表明我们之前尝试从类路径加载一个类,但由于某种原因它失败了 - 现在我们正在尝试再次使用该类(因此需要加载它,因为它上次失败了),但是我们'甚至没有尝试加载它,因为我们之前没有加载它(并且合理地怀疑我们会再次失败)。较早的失败可能是ClassNotFoundException或ExceptionInInitializerError(表示静态初始化块中的失败)或任何其他问题。关键是,NoClassDefFoundError不一定是类路径问题。从SRC库中删除两个文件后,我收到此消息,当我将它们带回来时,我一直看到此错误消息。
我的解决方案是:重启Eclipse。从那以后我再没有看到这个消息:-)
确保在module:app
和module:lib
中匹配:
android {
compileSdkVersion 23
buildToolsVersion '22.0.1'
packagingOptions {
}
defaultConfig {
minSdkVersion 17
targetSdkVersion 23
versionCode 11
versionName "2.1"
}
这是用来说明java.lang.NoClassDefFoundError
的代码。有关详细说明,请参阅Jared's answer。
no class def found error demo.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();
}
}
simple calculator.Java
public class SimpleCalculator {
static int undefined = 1 / 0;
}
我发现,当使用在运行时找到的类的不兼容版本编译代码时,有时会出现NoClassDefFound错误。我记得的具体实例是apache轴库。在我的运行时类路径上实际上有2个版本,它正在拾取过时和不兼容的版本而不是正确的版本,导致NoClassDefFound错误。这是在命令行应用程序中我使用类似于此的命令。
set classpath=%classpath%;axis.jar
我能够通过使用以下方式获取正确的版本:
set classpath=axis.jar;%classpath%;
NoClassDefFoundError在Java中
定义:
例子:
可能的解决方案:
资源:
这是我到目前为止发现的best solution。
假设我们有一个名为org.mypackage
的包,其中包含以下类:
定义此包的文件存储在D:\myprogram
(在Windows上)或/home/user/myprogram
(在Linux上)目录下。
当我们调用Java时,我们指定要运行的应用程序的名称:org.mypackage.HelloWorld
。但是,我们还必须告诉Java在哪里查找定义包的文件和目录。因此,要启动该程序,我们必须使用以下命令:
我在Spring Framework上使用Maven并在我的项目中解决了这个错误。
类中存在运行时错误。我正在读取一个属性为整数,但是当它从属性文件中读取值时,其值为double。
Spring没有给我一个关于运行时失败的哪一行的完整堆栈跟踪。它只是说NoClassDefFoundError
。但是当我将它作为本机Java应用程序(从MVC中取出)执行时,它给了ExceptionInInitializerError
这是真正的原因,这就是我如何跟踪错误。
@ xli的回答让我深入了解了我的代码可能出错的地方。
当运行时类加载器加载的类无法访问java rootloader已经加载的类时,我得到NoClassFoundError。因为不同的类加载器位于不同的安全域中(根据java),jvm将不允许在运行时加载器地址空间中解析已由rootloader加载的类。
用'java -javaagent:tracer.jar [你的java ARGS]'运行你的程序
它生成显示已加载类的输出,以及加载类的加载器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
,请特别阅读本文...一个有趣的案例,你可能会看到很多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
。