gvlasov
gvlasov

Reputation: 20025

How can Java deserialize Class objects while preserving their identity to currently loaded Class objects?

If I serialize a Class object (for example, HashMap.class), and then deserialize it in another instance of JVM, it turns out that the deserialized class is identical to the one currently loaded:

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.HashMap;

final class DeserializationTest {

    static String path = "/home/suseika/test.ser";
    static Class<HashMap> cls = HashMap.class;

    public static void main(String[] args) throws Exception {
        if (args[0].equals("serialize")) {
            serialize();
        } else if (args[0].equals("deserialize")) {
            final Object deserialized = deserialize();

            // The important line, prints "true"
            System.out.println(deserialized == cls); 
        }
    }

    static Object deserialize() throws Exception {
        ObjectInputStream in = new ObjectInputStream(new FileInputStream(path));
        return in.readObject();
    }

    static void serialize() throws Exception {
        FileOutputStream fileOut = new FileOutputStream(path);
        ObjectOutputStream out = new ObjectOutputStream(fileOut);
        out.writeObject(cls);
        out.close();
        fileOut.close();
    }
}

How is Java able to deserialize objects in this case so that identity is preserved? Class doesn't seem to implement writeObject()/readObject()/readResolve().

Can this behavior be broken with loading a particular class/using a particular classloader/using a particular JVM setup/doing something during serialization? Are there instances where the loaded Class would not be the same as the deserialized one? In other words, can I rely on this behavior in my application to serialize and deserialize Class objects?

Upvotes: 7

Views: 2604

Answers (2)

idelvall
idelvall

Reputation: 1661

How is Java able to deserialize objects in this case so that identity is preserved?

This is because class instances are cached by the classloader.

Does Java guarantee that Object.getClass() == Object.getClass()?

Can this behavior be broken with loading a particular class/using a particular classloader/using a particular JVM setup/doing something during serialization?

For serialized instances of classes from packages not starting with java.* this can be broken using different classloaders in ObjectInputStream (an example here).

For classes in java.* like your case (java.lang.Class), only the Bootstrap class loader can load them, and given that class definition is unique per class loader (guaranteed by the JVM spec)

In other words, can I rely on this behavior in my application to serialize and deserialize Class objects

Yes

Upvotes: 2

user207421
user207421

Reputation: 310957

How is Java able to deserialize objects in this case so that identity is preserved? Class doesn't seem to implement writeObject()/readObject()/readResolve().

It doesn't need to implement readObject() or writeObject() to accomplish this, but it could do it by implementing readResolve(), or by special logic in ObjectInputStream.

Upvotes: 0

Related Questions