专栏首页java 成神之路java 序列化 原理解析

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 方法

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

writeObjectOverride() 方法

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

writeObject0方法

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

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

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

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

writeOrdinaryObject 方法

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

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

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

writeExternalData 方法

实现 Externalizable 序列化接口

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

writeSerialData 方法

实现 Serializable 序列化接口

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

ObjectInputStream 原理解析

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

readObject 方法

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

readObject0 方法

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

readOrdinaryObject 方法

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

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

readExternalData 方法

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

readSerialData 方法

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

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

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


本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Java 序列化 之 Serializable

    java404
  • java 限流策略

    java404
  • 生成 Heap Dump 的几种方式

    java404
  • Java序列化进阶:Java内置序列化的三种方式

    Java序列化就是把Java对象按照一定的格式存到文件或者磁盘当中,那么Java内置的序列化有几种方式呢?每种方式的相同点和不同点是什么呢?

    哲洛不闹
  • Java基础-序列化与反序列化

    序列化和反序列化在面试中也经常考查,下面就总结一下 Java 中的序列化和反序列化。

    Wizey
  • 数据序列化的那些事

    为什么需要数据序列化呢?因为数据要“传输”,比如将数据网络通信传递给其他服务器,或者持久化到磁盘。那么传输为什么需要序列化呢?因为在内存中的数据,当前进程是知道...

    luoxn28
  • Python学习笔记 --- 序列化Serialization

    序列化 (serialization) 序列化是将对象状态转换为可保持或传输的格式的过程。与序列化相对的是反序列化,

    用户2398817
  • 夯实Java基础系列22:一文读懂Java序列化和反序列化

    本系列文章将整理到我在GitHub上的《Java面试指南》仓库,更多精彩内容请到我的仓库里查看

    Java技术江湖
  • Java序列化连环炮:是什么?为什么需要?如何实现?

    遇到这个 Java Serializable 序列化这个接口,我们可能会有如下的问题

    用户4143945
  • Java序列化 3 连问

    Java序列化是指把Java对象转换为字节序列的过程,而Java反序列化是指把字节序列恢复为Java对象的过程:

    xcbeyond

扫码关注云+社区

领取腾讯云代金券

玩转腾讯云 有奖征文活动