Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 900
gvlasov Avatar asked Mar 09 '16 12:03

gvlasov


1 Answers

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

like image 83
idelvall Avatar answered Oct 10 '22 13:10

idelvall