简体   繁体   中英

How can Serializable.class not be assignable from Class.class?

In org.springframework.core.SerializableTypeWrapper (version 5.2.3), there is the following code at line 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;
    }

I'm curious about the second check ( .Serializable.class.isAssignableFrom(Class.class) ): is it possible for it to evaluate to true (that is, for Serialazable.class to be not assignable from Class.class )?

Here is what Class#isAssignableFrom() javadoc says:

Determines if the class or interface represented by this Class object is either the same as, or is a superclass or superinterface of, the class or interface represented by the specified Class parameter.

Looking at the code of Class , I see the following:

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

So Serializable is a superinterface of Class and should always be assignable from Class . But the check in the Spring code suggests that sometimes it's not.

How come? In what situations can this happen and why don't they violate the Java Language Specification?

A custom class loader is a possible (if unlikely) mechanism for the expression to return false . Custom class loaders can do some crazy things, including loading their own versions of standard Java classes. Some things to know about class loaders:

  • Custom class loaders can be configured to load any class, even including Java standard library classes (it's discouraged of course, but still possible)
  • Custom class loaders will typically be configured to delegate to the system class loader for classes that they don't know how to load.
  • When class A has a reference to class B, the reference will be resolved using whichever class loader was used to load class A
  • More than one class loader can be configured to handle the same class, which can lead to multiple versions of a class getting loaded into the JVM, with the actual implementation you get depending on which class loader you ask

Suppose there is a custom class loader that, for whatever reason, is configured to load java.io.Serializable by itself, but delegates to the system class loader for loading other classes, including java.lang.Class .

Now suppose this custom class loader is used to load SerializableTypeWrapper . This means it will also be used to resolve the reference to java.io.Serializable in SerializableTypeWrapper . With the reference to java.lang.Class , the custom class loader will delegate this to the system class loader. The system class loader will be used to load java.lang.Class , but it will also be used to load the reference to java.io.Serializable from within java.lang.Class .

So now we can ask the question - is java.io.Serializable [custom] assignable from java.lang.Class [standard] ? And the answer is no - java.lang.Class does implement java.io.Serializable [standard] , but it does not implement java.io.Serializable [custom] .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM