《Java核心技术 卷Ⅱ 高级特性(原书第10版)》一2.4.2 理解对象序列化的文件格式

简介: 本节书摘来华章计算机《Java核心技术 卷Ⅱ 高级特性(原书第10版)》一书中的第2章 ,第2.4.2节,[美] 凯S.霍斯特曼(Cay S. Horstmann) 著陈昊鹏 译 更多章节内容可以访问云栖社区“华章计算机”公众号查看。

2.4.2 理解对象序列化的文件格式

对象序列化是以特殊的文件格式存储对象数据的,当然,你不必了解文件中表示对象的确切字节序列,就可以使用writeObject/readObject方法。但是,我们发现研究这种数据格式对于洞察对象流化的处理过程非常有益。因为其细节显得有些专业,所以如果你对其实现不感兴趣,则可以跳过这一节。
每个文件都是以下面这两个字节的“魔幻数字”开始的
image

后面紧跟着对象序列化格式的版本号,目前是
image

(我们在本节中统一使用十六进制数字来表示字节。)然后,是它包含的对象序列,其顺序即它们存储的顺序。
字符串对象被存为
image

字符串中的Unicode字符被存储为修订过的UTF-8格式。
当存储一个对象时,这个对象所属的类也必须存储。这个类的描述包含

  • 类名。
  • 序列化的版本唯一的ID,它是数据域类型和方法签名的指纹。
  • 描述序列化方法的标志集。
  • 对数据域的描述。

指纹是通过对类、超类、接口、域类型和方法签名按照规范方式排序,然后将安全散列算法(SHA)应用于这些数据而获得的。
SHA是一种可以为较大的信息块提供指纹的快速算法,不论最初的数据块尺寸有多大,这种指纹总是20个字节的数据包。它是通过在数据上执行一个灵巧的位操作序列而创建的,这个序列在本质上可以百分之百地保证无论这些数据以何种方式发生变化,其指纹也都会跟着变化。(关于SHA的更多细节,可以查看一些参考资料,例如William Stallings所著的《Cryptography and Network Security: Principles and Practice》第7版[Prentice Hall, 2016]。)但是,序列化机制只使用了SHA码的前8个字节作为类的指纹。即便这样,当类的数据域或方法发生变化时,其指纹跟着变化的可能性还是非常大。
在读入一个对象时,会拿其指纹与它所属的类的当前指纹进行比对,如果它们不匹配,那么就说明这个类的定义在该对象被写出之后发生过变化,因此会产生一个异常。在实际情况下,类当然是会演化的,因此对于程序来说,读入较旧版本的对象可能是必需的。我们将在2.4.5节中讨论这个问题。
下面表示了类标识符是如何存储的:

  • 72
  • 2字节的类名长度
  • 类名
  • 8字节长的指纹
  • 1字节长的标志
  • 2字节长的数据域描述符的数量
  • 数据域描述符
  • 78(结束标记)
  • 超类类型(如果没有就是70)

标志字节是由在java.io.ObjectStreamConstants中定义的3位掩码构成的:
image

我们会在本章稍后讨论Externalizable接口。可外部化的类提供了定制的接管其实例域输出的读写方法。我们要写出的这些类实现了Serializable接口,并且其标志值为02,而可序列化的java.util.Date类定义了它自己的readObject/writeObject方法,并且其标志值为03。
每个数据域描述符的格式如下:

  • 1字节长的类型编码
  • 2字节长的域名长度
  • 域名
  • 类名(如果域是对象)

其中类型编码是下列取值之一:
image

当类型编码为L时,域名后面紧跟域的类型。类名和域名字符串不是以字符串编码74开头的,但域类型是。域类型使用的是与域名稍有不同的编码机制,即本地方法使用的
格式。
例如,Employee类的薪水域被编码为:
image

下面是Employee类完整的类描述符:
image
image

这些描述符相当长,如果在文件中再次需要相同的类描述符,可以使用一种缩写版:
image

这个序列号将引用到前面已经描述过的类描述符,我们稍后将讨论编号模式。
对象将被存储为:
image

例如,下面展示的就是Employee对象如何存储:
image

正如你所看见的,数据文件包含了足够的信息来恢复这个Employee对象。
数组总是被存储成下面的格式:
image

在类描述符中的数组类名的格式与本地方法中使用的格式相同(它与在其他的类描述符中的类名稍微有些差异)。在这种格式中,类名以L开头,以分号结束。
例如,3个Employee对象构成的数组写出时就像下面一样:
image

注意,Employee对象数组的指纹与Employee类自身的指纹并不相同。
所有对象(包含数组和字符串)和所有的类描述符在存储到输出文件时都被赋予了一个序列号,这个数字以00 7E 00 00开头。
我们已经看到过,任何给定的类其完整的类描述符只保存一次,后续的描述符将引用它。例如,在前面的示例中,对Date类的重复引用就被编码为:
image

相同的机制还被用于对象。如果要写出一个对之前存储过的对象的引用,那么这个引用也会以完全相同的方式存储,即71后面跟随序列号,从上下文中可以很清楚地了解这个特殊的序列引用表示的是类描述符还是对象。
最后,空引用被存储为:
image

下面是前面小节中ObjectRefTest程序的带注释的输出。如果你喜欢,可以运行这个程序,然后查看其数据文件employee.dat的十六进制码,并将其与注释列表比较。在输出中接近结束部分的几行重要编码展示了对之前存储过的对象的引用。
image
image

当然,研究这些编码大概与阅读常用的电话号码簿一样枯燥。了解确切的文件格式确实不那么重要(除非你试图通过修改数据来达到不可告人的目的),但是对象流对其所包含的所有对象都有详细描述,并且这些充足的细节可以用来重构对象和对象数组,因此了解它还是大有益处的。
你应该记住:

  • 对象流输出中包含所有对象的类型和数据域。
  • 每个对象都被赋予一个序列号。
  • 相同对象的重复出现将被存储为对这个对象的序列号的引用。
相关文章
|
6月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
295 1
|
6月前
|
Java Unix Go
【Java】(8)Stream流、文件File相关操作,IO的含义与运用
Java 为 I/O 提供了强大的而灵活的支持,使其更广泛地应用到文件传输和网络编程中。!但本节讲述最基本的和流与 I/O 相关的功能。我们将通过一个个例子来学习这些功能。
264 1
|
6月前
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
317 1
|
9月前
|
监控 Java API
Java语言按文件创建日期排序及获取最新文件的技术
这段代码实现了文件创建时间的读取、文件列表的获取与排序以及获取最新文件的需求。它具备良好的效率和可读性,对于绝大多数处理文件属性相关的需求来说足够健壮。在实际应用中,根据具体情况,可能还需要进一步处理如访问权限不足、文件系统不支持某些属性等边界情况。
405 14
|
9月前
|
存储 安全 Java
深入理解Java序列化接口及其实现机制
记住,序列化不仅仅是把对象状态保存下来那么简单,它涉及到类的版本控制、安全性和性能等多个重要方面。正确理解和实现Java序列化机制对于构建高效、安全和可维护的Java应用至关重要。
278 0
|
10月前
|
JSON Java 数据库连接
|
10月前
|
存储 Java 数据安全/隐私保护
Java技术栈揭秘:Base64加密和解密文件的实战案例
以上就是我们今天关于Java实现Base64编码和解码的实战案例介绍。希望能对你有所帮助。还有更多知识等待你去探索和学习,让我们一同努力,继续前行!
613 5
|
9月前
|
存储 Java 编译器
深入理解Java虚拟机--类文件结构
本内容介绍了Java虚拟机与Class文件的关系及其内部结构。Class文件是一种与语言无关的二进制格式,包含JVM指令集、符号表等信息。无论使用何种语言,只要能生成符合规范的Class文件,即可在JVM上运行。文章详细解析了Class文件的组成,包括魔数、版本号、常量池、访问标志、类索引、字段表、方法表和属性表等,并说明其在Java编译与运行过程中的作用。
259 0
|
9月前
|
存储 人工智能 Java
java之通过Http下载文件
本文介绍了使用Java实现通过文件链接下载文件到本地的方法,主要涉及URL、HttpURLConnection及输入输出流的操作。
635 0
|
人工智能 自然语言处理 Java
FastExcel:开源的 JAVA 解析 Excel 工具,集成 AI 通过自然语言处理 Excel 文件,完全兼容 EasyExcel
FastExcel 是一款基于 Java 的高性能 Excel 处理工具,专注于优化大规模数据处理,提供简洁易用的 API 和流式操作能力,支持从 EasyExcel 无缝迁移。
3572 65
FastExcel:开源的 JAVA 解析 Excel 工具,集成 AI 通过自然语言处理 Excel 文件,完全兼容 EasyExcel