为啥Java对象实现serializable就能序列化与反序列化呢?

在 Java 里,一个对象只要实现了 `java.io.Serializable` 接口,就能被 `ObjectOutputStream/ObjectInputStream` 直接序列化/反序列化,根本原因是:

 

1. 接口本身只是一个“标记”(Marker Interface),没有任何待实现的方法;  

2. JVM 在运行期通过“类型检查”发现它打了这个标记,就会启用一套由 JDK 底层实现的默认序列化机制;  

3. 这套机制借助反射和 Unsafe 能力,绕过了构造器、访问修饰符等限制,把对象的整个图结构(类元数据、字段值、类型信息、引用关系)直接写进字节流,读回时再现场重建对象和引用关系。  

 

换句话说,实现 `Serializable` 只是给 JVM 发了一张“通行证”,真正干活的并不是接口,而是 JDK 里那套“看见通行证就自动触发”的 native 级实现。下面把关键步骤拆开讲。

 

---

 

一、标记接口:给 JVM 一个“开关”

- `Serializable` 接口体是空的,没有 `writeObject/readObject` 方法需要实现。  

- 运行期 `ObjectOutputStream` 会执行

 

  `if (obj instanceof Serializable)`

 

  只有返回 true 才继续,否则直接抛 `NotSerializableException`。

 

→ 它只是一个“运行期可见的布尔标志”,让序列化框架知道“这个类我敢写”。

 

---

 

二、默认序列化:JDK 的“黑盒”实现

当 `writeObject(obj)` 被调用时,JDK 在后台完成以下动作(简化版):

 

1. 拿到对象所属的 `Class<?>`,通过反射遍历其整个继承链(直到 `Object`)。  

2. 对每一个可序列化类,收集它的  

   - 类全名(`java.lang.String` 等)  

   - `serialVersionUID`(显式或计算)  

   - 所有非 transient 非 static 字段名、类型、值  

3. 如果字段是原始类型,直接按大端写值;

 

   如果是对象引用,递归地重复 13,直到把整个对象图展开成一棵“有向无环图”。  

4. 写流格式:

 

   `0x73` (TC_OBJECT)

 

   → 类描述符 (`TC_CLASSDESC`)

 

   → 字段值块 (`TC_BLOCKDATA`)

 

   → 引用句柄 (`TC_REFERENCE`) …

 

   这是 JVM 定义的私有协议,与 class 文件格式类似,但专为对象存储设计。  

5. 读回时,先读类描述符,再用 Unsafe.allocateInstance(Class) 直接绕过构造器生成空对象,然后把字段值按顺序“回填”进去,最后重建引用关系。

 

---

 

三、反射 + Unsafe:为什么“ private 字段也能动”

- 正常代码无法给 `private int x` 赋值,但 `ObjectStreamClass` 在初始化时会为每个字段生成一个 `FieldReflector`,底层调用

 

  `sun.misc.Unsafe.putInt(Object o, long offset, int x)`

 

  这条 native 指令可以无视访问控制,直接写内存。  

- 因此,即使字段全是 `private`、类没有 `setter`,序列化框架依旧可以“把内存原样搬走,再原样搬回来”。

 

---

 

四、显式自定义:什么时候需要 `writeObject/readObject`

- 如果类里写了

 

  `private void writeObject(ObjectOutputStream out) throws IOException`

 

  框架就会反射调用它,把控制权交给程序员;

 

  否则就走上面的默认算法。  

- 同理,`readObject` 允许你在反序列化完字段后再做校验、防御性拷贝、缓存重建等额外逻辑。

 

---

 

五、总结一句话

实现 `Serializable` 本身不做任何事,它只是让 JVM 的序列化框架“在运行期看见绿灯”;

 

绿灯一亮,JDK 就启动一套基于反射+Unsafe 的私有协议,把对象在内存中的完整状态“搬”到字节流里,再“搬”回来,于是看上去“实现了接口就能序列化”。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值