Java如何反序列化Class对象,同时保留它们与当前加载的Class对象的身份?

时间:2016-03-09 12:33:54

标签: java serialization classloader

如果我序列化Class对象(例如,HashMap.class),然后在另一个JVM实例中对其进行反序列化,则结果表明反序列化的类与当前加载的类相同: / p>

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();
    }
}

在这种情况下,Java如何能够反序列化对象,以便保留身份? Class似乎无法实施writeObject() / readObject() / readResolve()

在加载特定的类/使用特定的类加载器/使用特定的JVM设置/在序列化期间做某事时,是否可以破坏这种行为?是否存在加载的Class与反序列化的Class不同的情况?换句话说,我可以在我的应用程序中依赖此行为来序列化和反序列化 def fullname "#{first_name} #{last_name}" end 个对象吗?

2 个答案:

答案 0 :(得分:2)

  

在这种情况下,Java如何能够反序列化对象,以便保留身份?

这是因为类实例由类加载器缓存。

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

  

在加载特定的类/使用特定的类加载器/使用特定的JVM设置/在序列化过程中做某事时,是否可以破坏这种行为?

对于不以java.*开头的包中的类的序列化实例,可以使用ObjectInputStream中的不同类加载器(示例here)将其打破。

对于java.*中的类(例如java.lang.Class),只有Bootstrap类加载器可以加载它们,并且每个类加载器的类定义是唯一的(由JVM spec保证)

  

换句话说,我可以在我的应用程序中依赖此行为来序列化和反序列化Class对象

答案 1 :(得分:0)

  

在这种情况下,Java如何能够反序列化对象,以便保留身份? Class似乎没有实现writeObject()/readObject()/readResolve()

它不需要实现readObject()writeObject()来完成此任务,但它可以通过实施readResolve()ObjectInputStream中的特殊逻辑来实现。< / p>