【发布时间】:2021-11-01 10:07:50
【问题描述】:
ClassLoader clMain -> URLClassLoader clA(A 类,$B)。
$B 是类 A 的内部类 B。
- 从创建具有指定 URL 的新 clA 的 clMain 到包含 A 类(和 $B 类)的 jar 文件。然后通过 clA 创建新对象 A。
- 另一个类,从 X
ClassLoader加载,通过接口执行对象 A 的方法没有问题。 - 然后,在该方法中,应该创建新对象 $B,但它会抛出
NoClassDefFoundError。 - 在类A的构造函数中加载类$B解决问题:
this.getClass().getClassLoader().loadClass("A$B");
所以,提示是:“为什么在第 3 步找不到类 $B 的定义,可以用另一种方式解决这个问题吗?”
检查方法中使用的ClassLoader (this.getClass().getClassLoader()) 并将其与构造函数中使用的ClassLoader 进行比较 - 是相同的,并且包含必要的 url。
Java 8 和 14 尝试运行,jdk 8 构建。
编辑:
public class A {
public A(){
this.getClass().getClassLoader().loadClass("A$B"); // success
}
public void foo(){
this.getClass().getClassLoader().loadClass("A$B"); // success
new B(); // success
}
public static final class B {}
}
public class A {
public A(){
}
public void foo(){
this.getClass().getClassLoader().loadClass("A$B"); // throw
new B(); // Edit: added this line to demostrate what is not the main diff between two examples
}
public static final class B {}
}
编辑:此行为与内部类无关,而是与 jar 中的每个类相关。简而言之,我需要遍历 jar 中的每个类并在使用它们之前手动加载它们,否则 jvm 会抛出 NoClassDefFoundError。
【问题讨论】:
-
这似乎是jvm的一个奇怪特性。在创建对象以解决问题后,我只是使用 guava 库从我的包中加载所有类。 baeldung.com/java-find-all-classes-in-package
-
第二个示例中缺少
new B()是否可能相关?当字节码包含对另一个类的静态引用时,我可以想象不同的结果,而当它不包含时。为了绝对确定不是这个,你能测试一下吗?如果没有其他差异,我们只能确定是您的构造函数造成的。 -
@kaya3,不是真正的代码,而是一个示例。我将尝试创建一个重复此行为的测试项目。 |我真正的项目(正在开发中)我遇到的问题是github.com/p1k-Server/Server-env-test,分支dev。要重复这种情况,请参阅包含我的修复的提交“510a864c”(/Server)。
标签: java classloader