Java Object Serialization Specification: 5 - Versioning of Serializable Objects


5.1 概述

当Java对象使用序列化将状态保存在文件中,或作为数据库中的blob时,可能出现读取数据的类的版本与写入数据的类的版本不同的情况。

版本控制引发了一些关于类身份的基本问题,包括何为兼容更改。一个兼容更改是指不影响类与其调用者之间契约的更改。

本节描述了旨在通过限制允许的更改类型并仔细选择机制来解决此问题的目标、假设和解决方案。

提出的解决方案提供了一种机制,用于通过添加字段和添加类来“自动”处理逐渐演变的类。序列化将处理版本控制,无需为每个版本实现特定于类的方法。流格式可以在不调用特定于类的方法的情况下进行遍历。

5.2 目标

目标是:

5.3 假设

假设是:

5.4 谁负责流的版本控制

在类的演变过程中,演变(较新版本)类有责任维护未演变类建立的契约。这有两种形式。首先,演变类不得破坏原始版本提供的接口的现有假设,以便演变类可以替代原始版本。其次,在与原始(或先前)版本通信时,演变类必须提供足够和等效的信息,以允许早期版本继续满足未演变契约。

演变和未演变类及其实例之间的私有序列化协议和超类型关系

在这里讨论的目的是,每个类都实现并扩展其超类型定义的接口或契约。例如,类的新版本,例如foo',必须继续满足foo的契约,并且可以扩展接口或修改其实现。

通过序列化对象之间的通信不是这些接口定义的契约的一部分。序列化是实现之间的私有协议。实现有责任进行足够的通信,以允许每个实现继续满足其客户端期望的契约。

5.5 兼容的Java类型演变

Java语言规范讨论了Java类在演变过程中的二进制兼容性。二进制兼容性的灵活性大部分来自于对类、接口、字段、方法等名称的符号引用的延迟绑定。

以下是序列化对象流版本控制设计的主要方面。

5.6 影响序列化的类型更改

有了这些概念,现在我们可以描述设计如何处理演变类的不同情况。这些情况描述了由某个类的某个版本写入的流。当相同版本的类读取流时,不会丢失信息或功能。流是关于原始类的唯一信息来源。其类描述虽然是原始类描述的子集,但足以将流中的数据与正在重建的类版本匹配起来。

这些描述是从读取流以重建早期或后续版本的类的角度描述的。在RPC系统的术语中,这是一个“接收者正确”的系统。写入器以最合适的形式写入其数据,接收者必须解释该信息以提取所需部分并填充不可用的部分。

5.6.1 不兼容的更改

对类的不兼容更改是指无法保持互操作性保证的更改。在演变类时可能发生的不兼容更改包括:

5.6.2 兼容的更改

对类的兼容更改处理如下: