序列化深入实践:对象图、版本演进、安全沙箱与替代方案
大约 2 分钟
序列化深入实践:对象图、版本演进、安全沙箱与替代方案
新手先看 · 一屏速览
- Serializable 会持久化对象图;字段变更需维护 serialVersionUID
- 反序列化存在安全风险:只反序列化白名单类型;首选更安全的格式(JSON/Protobuf)
- 自定义 readObject/writeObject 控制读写;必要时 Externalizable
1. Serializable 基础
- 标记接口;默认按字段序列化对象图;transient 字段不序列化
- serialVersionUID 控制版本兼容;显式声明避免运行时计算差异
private static final long serialVersionUID = 1L;字段新增/删除/类型变化会影响兼容性;为长期存储制定演进策略
2. 自定义读写与高级钩子
private void writeObject(ObjectOutputStream out) throws IOException { out.defaultWriteObject(); }
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); }- 可用于写入额外校验或迁移逻辑
private Object writeReplace() throws ObjectStreamException { /* 返回代理对象 */ }
private Object readResolve() throws ObjectStreamException { /* 单例/缓存复用 */ }通过 writeReplace/readResolve 可实现序列化代理(Serial Proxy)模式,增强兼容性与不变式
3. Externalizable
- 完全由程序员控制读写格式;需显式无参构造
4. 版本演进与 serialPersistentFields
最近建一些几十个工作内推群,各大城市都有,群里目前已经收集了很多内推岗位,大厂、中厂、小厂、外包都有。 欢迎HR、开发、测试、运维和产品加入。

扫描下方微信,备注:网站+所在城市,即可拉你进工作内推群。

private static final ObjectStreamField[] serialPersistentFields = {
new ObjectStreamField("fieldA", int.class),
new ObjectStreamField("fieldB", String.class)
};通过显式字段列表控制兼容;对删除/重命名场景做兼容映射
5. 安全与替代
- 反序列化小心 gadget 链攻击:启用 JEP 290
ObjectInputFilter做白名单/黑名单 - 对外接口优先 JSON/CBOR/Protobuf/Avro(结合 Schema)替代 Java 原生序列化
- 内部强约束场景,至少限制可反序列化包前缀、类数量、图深度与总字节数
6. 实战清单与反模式
- 清单:显式 serialVersionUID;限制反序列化范围;优先安全格式
- 反模式:对外暴露 JDK 原生反序列化;忽视版本兼容;随意改变字段含义
7. 练习
- 编写自定义 ObjectInputStream,只允许特定包名下类反序列化
- 设计一次字段迁移策略并验证兼容性
