java 序列化 原理解析

序列化相关文章:

  • Java 序列化 之 Serializable
  • Java 序列化之 Externalizable
  • Java 序列化 之 单例模式。

阅读本文章之前,务必要阅读上面的三篇文章。
这篇文章是围绕上面三篇文章的原理进行剖析的。
因为 ObjectInputStream 和 ObjectOutputStream 类比较复杂,这里只解析跟上面三篇文章相关的内容。

java 序列化示例

public class Test{
    public static void main(String[] args) throws Exception {
        File file = new File("d:\\a.user");
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
        oos.writeObject(User.getInstance());
        oos.close();

        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
        User user = (User) ois.readObject();
        ois.close();
        System.out.println(user);
        
        if(user==User.getInstance()){
            System.out.println("同一个实例");
        }else{
            System.out.println("不同的实例");
        }
    }
}

通过该示例,我们知道 Java 序列化是由 ObjectInputStream 和 ObjectOutputStream 两个类实现的,下面我们就通过这两个类来揭开 Java 序列化的神秘面纱。

ObjectOutputStream 原理解析

writeObject 方法

java 序列化 原理解析_第1张图片

1、通过 enableOverride 判断是否执行 writeObjectOverride() 方法。
2、调用writeObject() 方法。

writeObjectOverride() 方法


通过源码发现这个方法是个空方法,这是搞什么鬼?
仔细分析后可以发现 writeObject 方法是final 类型的,也就是子类无法重写的,通过 向子类暴露 writeObjectOverride 方法来达到重写的目的。

writeObject0方法

java 序列化 原理解析_第2张图片

在 writeObject0() 方法中,跳过一些检查操作,直接分析最核心的这段代码。
1、 如果该对象是String、数组、枚举类型的,调用响应的方法进行写入。

在这里String和 Enum 类型不实现 Serializable 也可以序列化的,但String 类中还是实现了 Serializable 接口,告诉大家,该类可以序列化的。

2、如果对象是 Serializable 的,则调用 writeOrdinaryObject() 方法,该方法是序列化的核心方法。

在这里我们终于看到 Serializable的作用了。因为Serializable中没有定义方法,只是起到标识作用,该标识作用就在这提现。

writeOrdinaryObject 方法

java 序列化 原理解析_第3张图片

1、检查是否可以序列化
2、写入类型
3、写 class 的描述信息
4、判断是 该对象 否实现了 Externalizable 接口

  • 如果实现了则调用 writeExternalData 方法。
  • 如果没有实现则调用 writeSerialData 方法。

这里,我们可以看到,如果实现了 Externalizable 接口,会优先执行 Externalizable 接口的实现的方法,而默认的序列化方法不会执行。
这里也解释了上一篇文章中Java 序列化之 Externalizable 示例三 的原因。

writeExternalData 方法

实现 Externalizable 序列化接口


java 序列化 原理解析_第4张图片

通过该方法可以看到,在这里会调用我们自己定义的 WriteExternal() 方法。

writeSerialData 方法

实现 Serializable 序列化接口


java 序列化 原理解析_第5张图片
  • 1、判断该类是否定义了 writeObject() 方法,如果定义了,则通过反射调用该对象的 writeObject() 方法,执行我们自己定义的序列化规则。
  • 2、没有定义writeObject() 方法,则调用 defaultWriteFields() 方法执行默认的序列化规则。
    我们平常在重写 writeObject() 方法的时候一般也会先调用 defaultWriteFields() 方法的,然后在写上其它特殊的序列化。

ObjectInputStream 原理解析

ObjectInputStream 原理其实同 ObjectOutputStream 差不多,明白 ObjectInputStream 后再看 ObjectoutputStream 就很 easy 了。

readObject 方法

java 序列化 原理解析_第6张图片

1、提供给子类进行重写反序列化功能(readObject 方法是final的,但提供 readObjectOverride() 给子类去覆盖实现)
2、反序列化调用 readObject0() 方法去实现。

readObject0 方法

java 序列化 原理解析_第7张图片

该方法中提供了好多类型的反序列化方法支持。
但是我们这里只关注 Object类型的反序列化。这里调用的是 readOrdinaryObject() 。

readOrdinaryObject 方法

java 序列化 原理解析_第8张图片

1、判断该类是否实现了 Externalizable 接口,如果实现了Externalizable 接口,就执行readExternalData () 方法
2、否则,执行 readSerialData() 方法,使用默认的 Serializable 接口的反序列化方法执行发序列化。

3、判断该类是否定义了 readResolve() 方法,如果定义了 readResolveMethod() 方法,则执行用户定义的 readResolve() 方法。该方法的作用,请参考文章: Java 序列化 之 单例模式。

readExternalData 方法

java 序列化 原理解析_第9张图片

调用用户实现的 readExternal() 方法实现对象的反序列化。

readSerialData 方法

java 序列化 原理解析_第10张图片

判断用户是否实现了 readObject() 方法,如果实现,则执行用户自定义的发序列化方法。


java 序列化 原理解析_第11张图片

否则执行ObjectInputStream中默认的序列化方法 defaultReadFields();

通过ObjectOutputStream 类的简单分析,我们就可以了解到 Serializable 和 Externalizable 的原理。


想了解更多精彩内容请关注我的公众号

java 序列化 原理解析_第12张图片

你可能感兴趣的:(java 序列化 原理解析)