当我运行Java应用程序时,我得到了一个NoClassDefFoundError。造成这种情况的典型原因是什么?
当前回答
有一个有趣的例子,你可能会看到很多NoClassDefFoundErrors:
在类的静态块中抛出一个RuntimeException 拦截它(或者如果它在测试用例中抛出并不重要) 尝试创建该类的实例
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将伴随来自静态块RuntimeException的ExceptionInInitializerError一起抛出。
当你在UNIT TESTS中看到NoClassDefFoundErrors时,这一点尤其重要。
在某种程度上,您在测试之间“共享”静态块执行,但初始的ExceptionInInitializerError将仅在一个测试用例中。第一个使用有问题的Example类。其他使用Example类的测试用例只会抛出NoClassDefFoundErrors。
其他回答
这也可能是因为您从具有特定包名的IDE复制了代码文件,并且希望尝试使用终端运行它。您必须首先从代码中删除包名。 这种事发生在我身上。
如果有人因为java.lang.NoClassDefFoundError: org/apache/log4j/Logger错误来到这里,在我的例子中,它是因为我使用了log4j 2(但我没有添加它附带的所有文件),而一些依赖库使用了log4j 1。解决方案是添加Log4j 1。X桥:log4j-1.2-api-<version>.jar,随log4j 2而来。更多信息在log4j 2迁移中。
当运行时类装入器装入的类不能访问已经由java rootloader装入的类时,我得到NoClassFoundError。因为不同的类装入器在不同的安全域中(根据java), jvm不允许已经由rootloader装入的类在运行时装入器地址空间中被解析。
使用'java -javaagent:trace .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;
}
});
}
}
当我没有在项目的Java Build Path中的“Order and export”选项卡上导出一个类时,我得到了NoClassDefFound错误。确保在添加到项目构建路径的任何依赖项的“Order and Export”选项卡中添加一个复选标记。请参见Eclipse警告:XXXXXXXXXXX.jar将不会被导出或发布。可能会导致运行时ClassNotFoundExceptions。
这是迄今为止我找到的最好的解决办法。
假设我们有一个名为org的包。Mypackage包含的类:
HelloWorld(主类) SupportClass UtilClass
定义这个包的文件物理存储在目录D:\myprogram (Windows)或/home/user/myprogram (Linux)下。
文件结构如下所示:
当调用Java时,我们指定要运行的应用程序的名称:org.mypackage.HelloWorld。但是,我们还必须告诉Java在哪里查找定义包的文件和目录。所以要启动程序,我们必须使用下面的命令:
推荐文章
- URL从Java中的类路径加载资源
- .toArray(new MyClass[0]) or .toArray(new MyClass[myList.size()])?
- Hibernate中不同的保存方法之间有什么区别?
- Java 8流和数组操作
- Java Regex捕获组
- Openssl不被视为内部或外部命令
- 如何添加自定义方法到Spring Data JPA
- 如何在Ubuntu中设置Java环境路径
- 无法执行dex:在Eclipse中超过GC开销限制
- 有人能解释一下JPA和Hibernate中的mappedBy吗?
- 是什么导致JNI调用变慢?
- Java中的&和&&有什么区别?
- 使用Java的Collections.singletonList()?
- Maven使用多个src目录编译
- 导入时无法解析符号