首页 > 解决方案 > Serializable.class 怎么不能从 Class.class 分配?

问题描述

org.springframework.core.SerializableTypeWrapper(版本 5.2.3)中,第 112 行有以下代码:

    if (GraalDetector.inImageCode() || !Serializable.class.isAssignableFrom(Class.class)) {
        // Let's skip any wrapping attempts if types are generally not serializable in
        // the current runtime environment (even java.lang.Class itself, e.g. on Graal)
        return providedType;
    }

我对第二个检查 ( !Serializable.class.isAssignableFrom(Class.class)) 感到好奇:它是否可以评估为true(也就是说,Serialazable.class不能从 分配Class.class)?

这是Class#isAssignableFrom()javadoc 所说的:

确定此 Class 对象表示的类或接口是否与指定的 Class 参数表示的类或接口相同,或者是其超类或超接口。

查看 的代码Class,我看到以下内容:

public final class Class<T> implements java.io.Serializable

Serializable的超接口也是如此,Class并且应该始终可以从Class. 但 Spring 代码中的检查表明有时并非如此。

怎么来的?在什么情况下会发生这种情况,为什么它们不违反 Java 语言规范?

标签: javaspringgraalvmgraalvm-native-image

解决方案


自定义类加载器是表达式返回的一种可能(如果不太可能)机制false。自定义类加载器可以做一些疯狂的事情,包括加载他们自己版本的标准 Java 类。关于类加载器的一些知识:

  • 自定义类加载器可以配置为加载任何类,甚至包括 Java 标准库类(当然不鼓励,但仍然可以)
  • 自定义类加载器通常会配置为将它们不知道如何加载的类委托给系统类加载器。
  • 当 A 类引用 B 类时,将使用用于加载 A 类的任何类加载器来解析该引用
  • 可以配置多个类加载器来处理同一个类,这可能导致将一个类的多个版本加载到 JVM 中,您获得的实际实现取决于您询问的类加载器

假设有一个自定义类加载器,无论出于何种原因,它被配置为java.io.Serializable自行加载,但委托给系统类加载器以加载其他类,包括java.lang.Class.

现在假设这个自定义类加载器用于加载SerializableTypeWrapper. 这意味着它也将用于解析对java.io.Serializablein的引用SerializableTypeWrapper。通过对 的引用java.lang.Class,自定义类加载器会将其委托给系统类加载器。系统类加载器将用于加载java.lang.Class,但它也将用于java.io.Serializable从内部加载引用java.lang.Class

所以现在我们可以问这个问题 - 可以java.io.Serializable [custom]java.lang.Class [standard]? 答案是否定的——java.lang.Class执行java.io.Serializable [standard],但它不执行java.io.Serializable [custom]


推荐阅读