type
Post
status
Published
date
Jan 30, 2026 12:23 PM
slug
summary
序列化是将数据结构或对象转换为可存储或传输的形式的过程,反序列化则是将其恢复为原始状态。Java中实现序列化需实现java.io.Serializable接口,静态变量不会被序列化。序列化的常见协议包括JDK、Kryo、Protobuf/ProtoStuff和Hessian。JDK序列化存在跨语言调用支持差、性能低和安全问题等缺点。
tags
Java
category
八股盛宴
icon
password
序列化:将数据结构或对象转换成可以存储或传输的形式,通常是二进制字节流,也可以是 json、xml 等文本格式。
反序列化:将在序列化过程中所生成的数据转化为原始数据结构或者对象的过程。
序列化(serialization)在计算机科学的数据处理中,是指将数据结构或对象状态转换成可取用格式(例如存成文件,存于缓冲,或经由网络中发送),以留待后续在相同或另一台计算机环境中,能恢复原先状态的过程。依照序列化格式重新获取字节的结果时,可以利用它来产生与原始对象相同语义的副本。对于许多对象,像是使用大量引用的复杂对象,这种序列化重建的过程并不容易。面向对象中的对象序列化,并不概括之前原始对象所关系的函数。这种过程也称为对象编组(marshalling)。从一系列字节提取数据结构的反向操作,是反序列化(也称为解编组、deserialization、unmarshalling)。
常见序列化协议:
1. JDK
实现 JDK 自带的序列化,只需要实现 java.io.Serializable 接口即可。
Serializable 是标记接口,实现标记接口类仅仅是标记类为可序列化,并没有增加任何方法,该接口告诉 JVM 该类的对象已经准备好写入持久性存储或者通过网络读取。
静态变量不会被序列化,因为其不是对象本身的一部分。
默认情况,JVM 负责编写和读取可序列化对象的过程。序列化或者反序列化的功能通过对象流类的以下两种方法公开:
- ObjectOutputStream writeObject(Object): 将可序列化的对象写入输出流。
- ObjectInputStream readObject(): 从输入流读取(寻找到序列化类之后)构造并返回一个对象。
对于可序列化类需要注意两个成员变量:
- serialVersionUID:常数,用于唯一标识可序列化类的版本。从输入流构造对象时,JVM 检查此常数。serialVersionUID是可选的,这意味着即使不显示声明,编译器会基于类的元素自动生成(如果元素变化,serialVersionUID 也会随之变化),这也是显示指明的优点,即类的修改不会导致序列化失败。
A serializable class can declare its own serialVersionUID explicitly by declaring a field named "serialVersionUID" that must be static, final, and of type long;
- transient:标记瞬时变量,JVM 不会序列化并存储此变量值,在反序列化后变量值被设置为类型默认值。
不推荐使用
很少或者说几乎不会直接使用 JDK 自带的序列化方式,主要原因有下面这些原因:
不支持跨语言调用 : 如果调用的是其他语言开发的服务的时候就不支持了。
性能差:相比于其他序列化框架性能更低,主要原因是序列化之后的字节数组体积较大,导致传输成本加大。
存在安全问题:序列化和反序列化本身并不存在问题。但当输入的反序列化的数据可被用户控制,那么攻击者即可通过构造恶意输入,让反序列化产生非预期的对象,在此过程中执行构造的任意代码。
2. Kryo
3. Protobuf / ProtoStuff
4. Hessian
- 作者:宗海
- 链接:https://nowave.cloud//article/1f7beb96-1d72-80d7-829f-cf6b867f98d5
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。







