Java ClassLoader:是否可以配置为使用惰性而非静态解析?
我读到它是关于分辨率的 解析是检查从测试到其他类和接口的符号引用的过程,方法是加载提到的其他类和接口,并检查引用是否正确 在初始链接时,解析步骤是可选的。一个实现可以解析早期链接的类或接口的符号引用,甚至可以解析进一步递归引用的类和接口的所有符号引用 相反,一个实现可以选择仅在符号引用被积极使用时解析它;对所有符号引用一致使用此策略将代表“最懒惰”的解析形式。在这种情况下,如果测试有多个对另一个类的符号引用,那么引用可能会在使用时一次解析一个,或者如果这些引用在程序执行期间从未使用过,则可能根本不会解析 例如,实现可以选择仅在使用时单独解析类或接口中的每个符号引用(延迟解析或延迟解析),或者在验证类时一次性解析所有符号引用(静态解析)。这意味着在某些实现中,在类或接口初始化之后,解析过程可能会继续 所以我的问题是我是否可以选择/强制使用惰性初始化?也许它需要编写一个自定义类加载器?或者启动时类加载器中的ClassNotFoundException可能会被忽略Java ClassLoader:是否可以配置为使用惰性而非静态解析?,java,jvm,classloader,Java,Jvm,Classloader,我读到它是关于分辨率的 解析是检查从测试到其他类和接口的符号引用的过程,方法是加载提到的其他类和接口,并检查引用是否正确 在初始链接时,解析步骤是可选的。一个实现可以解析早期链接的类或接口的符号引用,甚至可以解析进一步递归引用的类和接口的所有符号引用 相反,一个实现可以选择仅在符号引用被积极使用时解析它;对所有符号引用一致使用此策略将代表“最懒惰”的解析形式。在这种情况下,如果测试有多个对另一个类的符号引用,那么引用可能会在使用时一次解析一个,或者如果这些引用在程序执行期间从未使用过,则可能根本
我在
main
中有一个对象的有条件创建,它实际上不应该发生,并且jar中缺少相应的类。但是,即使在main
开始执行之前,NoClassDefFoundError
也会被抛出。NoClassDefFoundError错误:
如果Java虚拟机或类加载器
实例
尝试加载类的定义(作为普通方法调用的一部分
或者作为使用new
表达式创建新实例的一部分)
并且找不到该类的定义
该错误与实例化相关类的实例无关。因此,对于您的示例,如果“outer”类为该类型定义了一个字段,就足够了。无法加载包含main的类,因为它所依赖的类型在运行时在类路径上不可用
如果有疑问,请查看导入语句并删除要动态加载的类的导入*)。然后尝试删除错误标记,而不再次为该类添加导入
*)-我假设此动态加载的类位于不同的包中,您需要为其导入。NoClassDefFoundError错误: 如果Java虚拟机或
类加载器
实例
尝试加载类的定义(作为普通方法调用的一部分
或者作为使用new
表达式创建新实例的一部分)
并且找不到该类的定义
该错误与实例化相关类的实例无关。因此,对于您的示例,如果“outer”类为该类型定义了一个字段,就足够了。无法加载包含main的类,因为它所依赖的类型在运行时在类路径上不可用
如果有疑问,请查看导入语句并删除要动态加载的类的导入*)。然后尝试删除错误标记,而不再次为该类添加导入
*)-我假设这个动态加载的类位于不同的包中,您需要为其导入。您不能使用Oracle的JVM
根据定义,类加载器不能延迟类的加载。链接的顺序和时间是特定于实现的。AFAIK大多数JVM选择尽早链接,有些甚至在编译时链接(请参阅Excelsior JET以获取此示例)。您不能使用Oracle的JVM 根据定义,类加载器不能延迟类的加载。链接的顺序和时间是特定于实现的。AFAIK大多数JVM选择尽早链接,有些甚至在编译时链接(请参阅Excelsior JET以获取此示例)。考虑一下这一点
class Test2 {
}
public class Test1 {
static Test2 test2;
public static void main(String[] args) {
System.out.println("Test1");
test2 = new Test2();
}
}
我编译了它,删除了Test2.class并运行了java-cp。Test1
输出
Test1
Exception in thread "main" java.lang.NoClassDefFoundError: Test2
at Test1.main(Test1.java:9)
Caused by: java.lang.ClassNotFoundException: Test2
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
......
在我看来,这意味着JVM依赖项解析在默认情况下是惰性的。JVM直到第一次使用Test2.class时才注意到它丢失了
class Test2 {
}
public class Test1 {
static Test2 test2;
public static void main(String[] args) {
System.out.println("Test1");
test2 = new Test2();
}
}
我编译了它,删除了Test2.class并运行了java-cp。Test1
输出
Test1
Exception in thread "main" java.lang.NoClassDefFoundError: Test2
at Test1.main(Test1.java:9)
Caused by: java.lang.ClassNotFoundException: Test2
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
......
在我看来,这意味着JVM依赖项解析在默认情况下是惰性的。JVM直到第一次使用Test2.class时才注意到它丢失了。Andreas_D说的是非常正确的:你可以按照你要求的方式解决问题。Andreas_D说的是非常正确的:你可以按照你要求的方式解决问题。谢谢,我理解你在这里的意思。但是我能做什么呢?如果你不能使用运行时已知的接口,那么你必须将实例存储为
对象
类型,并反映字段和方法。谢谢,我理解你在这里的意思。但是我能做什么呢?如果你不能使用运行时已知的接口,那么你必须将实例存储为对象
类型,并反映字段和方法。是的,你是对的。我已经对这段代码做了实验,也在不同的包中进行了分离,放入jar,并始终在异常/错误之前获取Test1
。但在我的真实代码中,异常是先打印的,而不是main
中的println
。是的,您