Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 557
Roman Puchkovskiy Avatar asked Jul 24 '20 06:07

Roman Puchkovskiy


People also ask

How do you make a class not serializable?

In order to prevent subclass from serialization we need to implement writeObject() and readObject() methods which are executed by JVM during serialization and deserialization also NotSerializableException is made to be thrown from these methods.

What happens if your serializable class contains a member which is not serializable?

It'll throw a NotSerializableException when you try to Serialize it. To avoid that, make that field a transient field.

How do you declare a class which has fields that are not serializable?

MyClass will have to implement custom serialization by providing readObject and writeObject methods. the non-serializable field's Class must have an API to allow getting it's state (for writing to the object stream) and then instantiating a new instance with that state (when later reading from the object stream.)

How an object can become serializable if a class or any superclass implements Java IO serializable interface if a class implements Java IO serializable class?

Correct Option: C. A Java object is serializable if class or any its superclass implements java. io. Serializable or its subinterface java.


1 Answers

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].

like image 190
Kevin K Avatar answered Oct 06 '22 00:10

Kevin K