[转帖]JAVA 对象序列化

java,对象,序列化 · 浏览次数 : 0

小编点评

**文章解析** 文章介绍了 Java 中的序列化机制,包括 ObjectInputStream 和 ObjectOutputStream。 * **序列化**是一种将对象写入二进制文件或从二进制文件中读取对象的过程。 * **ObjectInputStream** 用于读取二进制文件,并将其解码成对象。 * **ObjectOutputStream** 用于写入二进制文件,并将其编码成对象。 * **main** 函数展示了序列化对象的步骤,包括创建对象,使用 ObjectInputStream 和 ObjectOutputStream 将对象写入和读取文件。 * **对象类型描述**包含字段类型、名称长度和描述。 * **序列化结束符**用于标记对象类型信息的结束。 **重要概念** * **魔数**:标识文件类型。 * **序列化类型**:指当前对象可序列化的类型。 * **字段类型**:指当前字段的类型。 * **对象类型描述**:包含所有字段类型和名称。 **示例** 假设我们有一个名为 `People` 的类,它包含三个字段:`name`, `age` 和 `address`。以下是其序列化过程的示例: 1. 创建一个 `People` 对象。 2. 使用 `ObjectOutputStream` 将对象写入二进制文件。 3. 使用 `ObjectInputStream` 从二进制文件读取对象。 **结论** 通过使用 ObjectInputStream 和 ObjectOutputStream,我们可以将 Java 对象写入和读取二进制文件,并根据对象类型描述来解析和设置字段的值。

正文

https://cloud.tencent.com/developer/news/276874

 

所谓的『JAVA对象序列化』就是指,将一个JAVA对象所描述的所有内容以文件IO的方式写入二进制文件的一个过程。关于序列化,主要涉及两个流,ObjectInputStream和ObjectOutputStream。

 

稍显复杂的main函数:

 

可以看到,这种古老的序列化方式其实就是使用流DataInput/OutputStream将对象中字段的值逐个的写入文件,完成所谓的『序列化操作』。恢复对象的时候也必须按照写入的顺序一个字段一个字段的读取,这种方式可以说非常的反人类了,如果一个类有一百个字段,岂不是得手动写入一百次。这种方式准确意义上来说并不能算作『序列化』的一种实现,它是一种伪序列化,大家知道一下就好了。

 

输出结果:single23ObjectOutputStream某种意义上来看也是一种装饰者流,内部所有的字节流操作都依赖我们构造实例时传入的OutputStream实例。这个类的实现很复杂,光内部类就定义了很多,同时它也封装了我们的DataOutputStream,所以DataOutputStream那一套写基本数据类型的方法,这里也有。

 

序列化后的对象需要用这么多的二进制位进行存储,这些二进制位都是符合JAVA的序列化规则的,每几个字节用来存储什么都是规定好的,下面我们一起来看看。1、魔数:这个是几乎所有的二进制文件头部都有的,用于标识当前二进制文件的文件类型,我们的对象序列化文件的魔数是ACED,占两个字节。

 

注意,字符串和数组类型并没有划分到普通的Java对象这一类中,它们具有不同的数值标志。我们这里的People是一个普通的Java对象,所以这里是0x73。4、一个字节:这一个字节指明当前的对象所属的数据类型,是一个类或者是一个引用,这里的引用区别于Java的引用指针。

 

6、序列号版本:接下来的八个字节,3A->B5描述的是当前类对象的序列化版本号,这个值由于我们定义的People类中没有显式指明,所以编译器会根据People类的相关信息以某种算法生成一个serialVersionUID占八个字节。7、序列化类型:一个字节,用于指明当前对象的序列化类型,0x02即代表当前对象可序列化。

 

9、字段类型:一个字节,0x4C对应的ASCII值为L,即表示当前字段的类型是一个普通类类型。10、字段名长度:两个字节,0x0003指明接下来的三个字节表述了当前字段的全名称,0x616765正好对应字符age。

 

12、字段描述结束符:一个字节,固定值0x78标志所有的字段类型信息描述结束。13、父类类型描述:一个字节,0x70代表null,即没有父类,不算Object类。接下来这一段其实是Java序列化一个Integer对象的过程,然后到0x7872,即Integer类还有父类,于是又去序列化一个父类Number实例。

 

最后一个0x7870,说明所有的对象信息都已经序列化完成,下面是各个字段的数据部分。前四个字节,0x00000017是我们第一个字段age的值,也就是23。0x74指明第二个字段的类型是String类型,值的长度0x0006,最后六个字节刚好是字符串single。

 

这两个类的定义几乎就是相同的,内部都定义了一个People字段。

 

让ClassA和ClassB的两个对象公用同一个People实例,那么有一个问题,我去序列化这两个对象,这个公用的People对象会被序列化两次吗?我们打开二进制文件,这次的二进制文件要复杂一点了:

 

我圈出来了几个0x7870,它标志着一个对象类型信息的序列化结束,我们简单分析一下,不会详细的说了,具体参照上面的内容。第一部分其实是在序列化ClassA类型,它指明了ClassA类型只有一个字段,并且该字段是一个对象类型,记录下字段的类型名称等信息。第二部分在序列化People类型,包括序列化其中的name字段,并存储了name字段的外部赋的值,字符串:single。

 

其中,阴影部分是ClassB类的全限定名,红线框是该类的版本序列号,由于我们没有显式指定,这是由编译器自动生成的。接着指明具有一个字段,字段类型是对象类型,名称长度六个字节。0x71指明这个字段是一个引用,按惯例来说,这部分应该进行该字段的类型名称描述,但是由于这种类型已经序列化过了,所以使用引用直接指向前面已经完成序列化的People类型。

 

name被关键字transient修饰,即默认的序列化机制不会序列化该字段,并且我们重写了writeObject和readObject,在其中调用了默认的序列化方法之后,我们分别将name字段写入和读出。

与[转帖]JAVA 对象序列化相似的内容:

[转帖]JAVA 对象序列化

https://cloud.tencent.com/developer/news/276874 文章来源:企鹅号 - 燃照爱宠物 所谓的『JAVA对象序列化』就是指,将一个JAVA对象所描述的所有内容以文件IO的方式写入二进制文件的一个过程。关于序列化,主要涉及两个流,ObjectInputStre

[转帖]Java IO篇:序列化与反序列化

1、什么是序列化: 两个服务之间要传输一个数据对象,就需要将对象转换成二进制流,通过网络传输到对方服务,再转换成对象,供服务方法调用。这个编码和解码的过程称之为序列化和反序列化。所以序列化就是把 Java 对象变成二进制形式,本质上就是一个byte[]数组。将对象序列化之后,就可以写入磁盘进行保存或

[转帖]Java IO篇:序列化与反序列化

1、什么是序列化: 两个服务之间要传输一个数据对象,就需要将对象转换成二进制流,通过网络传输到对方服务,再转换成对象,供服务方法调用。这个编码和解码的过程称之为序列化和反序列化。所以序列化就是把 Java 对象变成二进制形式,本质上就是一个byte[]数组。将对象序列化之后,就可以写入磁盘进行保存或

[转帖]如何通过JMeter测试金仓数据库KingbaseES并搭建环境

1.安装JMeter Apache JMeter是Apache组织开发的基于Java的压力测试工具,主要用于对软件的压力测试,它最初被设计用于Web应用测试,但后来扩展到其它测试领域。它可测试静态、动态资源,如静态文件、Java小服务程序、CGI脚本、Java对象、数据库等等。JMeter可以用于对

[转帖]HotSpot 虚拟机对象探秘

https://www.cnblogs.com/xiaojiesir/p/15593092.html 对象的创建 一个对象创建的时候,到底是在堆上分配,还是在栈上分配呢?这和两个方面有关:对象的类型和在 Java 类中存在的位置。 Java 的对象可以分为基本数据类型和普通对象。 对于普通对象来说,

[转帖]Cat导致内存不足原因分析

背景 线上几亿的数据在回刷的时候容器服务会出现OOM而重启,导致任务中断 内存泄露分析 jmap -histo pid 找出了有几十亿的java.lang.StackTraceElement对象,找不到被谁引用了 jmap -dump:format=b,file=heapdump.hprof pid

[转帖]【JVM】类加载机制

什么是类的加载 将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构。类的加载的最终产品是位于堆区中的Class对象,Class对象封装了类在方法区内的数据结构,并且向Java程序员提供

[转帖]一个用于辅助分析‘Java内存泄露’的小工具

https://www.jianshu.com/p/658cb6cbfe61 histo对比工具 这是一个用于辅助分析‘Java内存泄露’的小工具 源码地址 实现原理 分析fgc前后的类实例对象分布变化来辅助判断 如果多次fgc后,一个类的对象实例没有发生变化或者越来越多,则需要重点排查 操作步骤

[转帖]【JVM】堆内存与栈内存详解

堆和栈的定义 java把内存分成栈内存和堆内存。 (1)栈内存 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配。 当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间,当超过变量的作用域后,java会自动释放掉为该变量分配的内存空间,该内存空间可以立刻被另

[转帖]查看堆内对象的工具:jmap

文章目录 用途命令格式示例一,no option二,heap三,histo[:live]四,clstats五,finalizerinfo六,dump: 用途 jmap 可以查看堆内对象的信息,生成 java 程序的 dump 文件,甚至可以查看 ClassLoader 的