loadClass(String name)和loadClass(String name,boolean resolve)之间的区别

时间:2011-03-25 05:06:47

标签: java classloader

loadClass(String name)loadClass(String name, boolean resolve)之间的区别是什么?

我知道的唯一区别是loadClass(String name, boolean resolve)如果resolve参数为真,则调用findLoadedClass(String)?

那么什么时候将true或false传递给resolve参数?
我对这两个功能感到很困惑。

感谢。

3 个答案:

答案 0 :(得分:3)

resolve参数控制是否链接了已加载的类。在链接期间,初始化静态常量并分配其内存。此外,还会验证该类的正确性,并且可能会解析与其他类的链接。

这可能很有用,例如,如果您想加载一个可能格式错误的新类,并且不希望JVM在类错误的情况下抛出验证错误。

答案 1 :(得分:1)

当第一次使用(或至少使用过的部分)时,该类仍然是链接的 - 使用resolve标志可以使VM立即执行此链接(并抛出相关错误)而不是以后

答案 2 :(得分:1)

你可以尝试一下。

public class Test3  {

    static{
         new Test();
    }   
}

编译之后,将Test Class从具体类更改为interface.but仍然是Test3链接到具体的Class Test。然后,如果resolve为false,JVM将不会发现此错误。这非常有趣。实际上,Class someClass1= Class.forName("Test3",false,cls)也不会解析Test3。这意味着不会抛出任何错误。

但是如果你在subClass或Class.forName("Test3")中设置resolve true,那么运行时的JVM会发现类链接错误。

Exception in thread "main" java.lang.InstantiationError: Test
    at Test3.<clinit>(Test3.java:6)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:169)

供您参考,Java语言规范 - 12.3 Linking of Classes and Interfaces解释了resolveClass的作用。

  

12.3 链接类和接口   链接是获取类或接口类型的二进制形式并将其组合到Java虚拟机的运行时状态的过程,以便可以执行它。始终在链接之前加载类或接口类型。   链接涉及三个不同的活动:验证,准备和解决符号引用。链接的精确语义在Java虚拟机规范第二版的第5章中给出。在这里,我们从Java编程语言的角度概述了该过程。

     

12.3.3符号引用的解析   类或接口的二进制表示使用其他类和接口的二进制名称(第13.1节)(第13.1节)以符号方式引用其他类和接口及其字段,方法和构造函数。 For在这些字段和方法中,这些符号引用包括声明字段或方法的类或接口类型的名称,以及字段或方法本身的名称,以及适当的类型信息。   在使用符号引用之前,它必须经过解析,其中符号引用被检查为正确,并且通常用直接引用替换,如果重复使用引用,则可以更有效地处理。

     

如果在解析期间发生错误,则会引发错误。最典型的情况是,这将是类 IncompatibleClassChangeError 的以下子类之一的实例,但它也可能是IncompatibleClassChangeError的某个其他子类的实例,甚至是类IncompatibleClassChangeError本身的实例。在程序中的任何一点都可能抛出此错误,该错误直接或间接地使用对该类型的符号引用:

     

IllegalAccessError :遇到符号引用,指定字段的使用或赋值,或方法的调用,或类的实例的创建,包含引用的代码没有访问权限,因为字段或方法被声明为私有,受保护或默认访问(非公共),或者因为该类未被声明为public。   例如,如果最初声明为public的字段在引用该字段的另一个类已经编译之后被更改为私有(第13.4.6节),则会发生这种情况。

     

InstantiationError :遇到了在类实例创建表达式中使用的符号引用,但无法创建实例,因为引用结果是引用接口或抽象类。   例如,如果在编译了引用相关类的另一个类(第13.4.1节)之后,最初不是抽象的类被更改为抽象,则会发生这种情况。

     

NoSuchFieldError :遇到了一个符号引用,它引用了特定类或接口的特定字段,但该类或接口不包含该名称的字段。   例如,如果在编译引用该字段的另一个类(第13.4.7节)之后从类中删除了字段声明,则会发生这种情况。

     

NoSuchMethodError :遇到了一个符号引用,它引用了特定类或接口的特定方法,但该类或接口不包含该签名的方法。   例如,如果在编译引用该方法的另一个类(第13.4.11节)之后从类中删除了方法声明,则会发生这种情况。   此外,如果类声明了无法找到实现的本机方法,则可能会抛出 UnsatisfiedLinkError LinkageError 的子类)。如果使用该方法或更早,则会发生错误,具体取决于虚拟机使用的解析策略类型(第12.3节)。