【问题标题】:Class instance obtained through multiple class loader通过多个类加载器获得的类实例
【发布时间】:2011-03-21 08:36:20
【问题描述】:

我正在阅读this 文章,它说:

如果我们有两个由这些 CustomClassLoader 加载的 Student 类的实例,比如 student1 和 student2,那么 student1 和 student2 不是类型兼容的。换句话说,

学生 student3 = (学生) student2;

将抛出 ClassCastException,因为 JVM 将这两个视为独立的、不同的类类型,因为它们是由不同的 ClassLoader 实例定义的。

现在我明白了它想要传达的意思:如果我们使用两个不同的类加载器加载同一个类,那么它们将不兼容。到目前为止一切都很好。

但是它使用的例子让我很困惑,即

学生 student3 = (学生) student2;

难道不是当我们声明像 Student student 这样的引用变量时,编译器所寻找的只是这个 Studnet 是否存在在符合其包结构的适当位置。现在,当我们在运行时将此引用变量分配给一个真正加载的类时,我们使用哪个类加载器来加载所述类真的重要吗?我怀疑,因为根据我的理解,类加载器仅在我们执行“新建”或在其上调用静态字段时才起作用,而不是在我们简单地声明它的类型时。

请就此澄清一下,并帮助我纠正我在这方面的理解。

谢谢, 马维亚

【问题讨论】:

    标签: java classloader


    【解决方案1】:

    这基本上是正确的,但是当分配发生时,JVM 需要确保它是正确的。所以它会检查:我可以将右侧 (RHS) 分配给左侧 (LHS)。

    规则说,当您可以将 RHS 的运行时类型向下转换为 LHS 的类型时,这是允许的。

    所以在编译时,上面的代码看起来没问题。但是在运行时,调用isAssignableFrom()返回false,因为这两种类型不同。

    Class 中的方法equals() 如果限定名称相同并且 相同,则返回true。这就是为什么在这种情况下你会得到ClassCastException

    所使用的方法是作为本机代码实现的,因此您看不到发生了什么。但是 isInstance()isAssignableFrom() 方法只有在两个类的类加载器相同时才返回 true。

    【讨论】:

    • 但是是什么让jvm认为两者是不同的。直到现在还没有类加载器与student3关联。只有 student2 被分配给某个类加载器加载的对象。
    • @mawia:是的,有:为了进行检查,JVM 必须为student3 加载类。所以你可以说类加载也发生在变量赋值上。或者当你打电话给Class.forName()
    【解决方案2】:

    是的,在运行时,哪个类加载器加载了一个类确实很重要。并且每次必须加载类时都会检查类加载器。这不仅是在遇到new 或静态字段时。每当类名出现在 Java 代码中时,或更准确地说,当在字节码中引用类名并执行字节码时,就会发生这种情况。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-07-23
      • 1970-01-01
      • 2016-06-30
      • 1970-01-01
      • 2014-11-18
      • 1970-01-01
      相关资源
      最近更新 更多