当前位置: 首页 > news >正文

java反序列化小记

🧾 整体目标

将一个 Person 对象转换为字节流(序列化),再从字节流还原成对象(反序列化),验证 Java 序列化机制的行为。


🔹 第一部分:序列化(把对象变成字节)

// 1. 序列化
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
Person p1 = new Person();
p1.name = "Alice";
oos.writeObject(p1);

逐行解释:

代码作用
ByteArrayOutputStream baos = new ByteArrayOutputStream();创建一个内存中的字节输出流,用于临时存储序列化后的数据(不写入文件或网络)
ObjectOutputStream oos = new ObjectOutputStream(baos);包装 baos,创建一个对象输出流,专门用于写入可序列化的对象
Person p1 = new Person();创建一个 Person 实例(会调用构造函数)
p1.name = "Alice";给字段赋值
oos.writeObject(p1);将 p1 序列化为字节,并写入 baos

此时,baos 中保存了 p1 的完整状态(字段名 + 字段值 + 类信息 + serialVersionUID 等)

💡 注意:如果 Person 没有实现 Serializable 接口,这一步会抛出 NotSerializableException


🔹 第二部分:反序列化(把字节变回对象)

// 2. 反序列化
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);System.out.println("开始反序列化...");
Person p2 = (Person) ois.readObject(); // ← 关键行
System.out.println("反序列化完成");

逐行解释:

代码作用
baos.toByteArray()获取序列化后的原始字节数组
ByteArrayInputStream bais = new ByteArrayInputStream(...);创建一个内存中的字节输入流,用于读取这些字节
ObjectInputStream ois = new ObjectInputStream(bais);包装 bais,创建对象输入流,用于读取对象
ois.readObject()从流中读取字节,并重建对象 → 这是反序列化的入口

🔥 关键:JVM 在 ois.readObject() 中自动调用了哪些方法?

ois.readObject() 执行时,JVM 会按顺序检查并自动调用以下特殊方法(如果存在):

✅ 1. readObject(ObjectInputStream in)

  • 签名必须严格匹配
    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
  • 作用:自定义反序列化逻辑(如校验、解密、初始化 transient 字段)
  • 调用时机:在恢复字段值之后(如果你调用了 in.defaultReadObject())或之前
  • 权限:即使 private,JVM 也会通过反射调用

✅ 2. readResolve()

  • 签名
    private Object readResolve() throws ObjectStreamException
  • 作用:替换反序列化出来的对象(常用于单例模式保护、代理对象返回等)
  • 调用时机:在 readObject 完成后、返回对象前
  • 示例
    private Object readResolve() {return MySingleton.getInstance(); // 确保反序列化不会破坏单例
    }

❌ 不会调用的方法:

  • 构造函数(Constructor):反序列化不调用任何构造函数(包括无参构造)
  • 普通方法:除非你在 readObject 中显式调用

📌 补充:序列化时也会自动调用的方法

对应地,在 oos.writeObject(p1) 时,JVM 也会检查:

✅ writeObject(ObjectOutputStream out)

  • 自定义序列化逻辑(如加密字段、跳过某些字段)
  • 签名:
    private void writeObject(ObjectOutputStream out) throws IOException

✅ writeReplace()

  • 替换要被序列化的对象(类似 readResolve 的反向)

🧪 完整流程图(反序列化阶段)

调用 ois.readObject()↓
JVM 检查 Person 类是否有 readObject()↓
是 → 通过反射调用 Person.readObject(in)↓
在 readObject 中通常调用 in.defaultReadObject() → 恢复字段值↓
JVM 检查是否有 readResolve()↓
是 → 调用 readResolve(),用其返回值作为最终对象↓
返回对象给 p2

✅ 总结:你这段代码的作用

步骤作用
序列化将 Person("Alice") 转为字节数组,存入内存流
反序列化从字节数组重建 Person 对象,不调用构造函数,但会自动回调 readObject()(如果存在)
安全意义如果 readObject() 中包含危险操作(如执行命令、触发反射链),攻击者可通过伪造字节流实现 RCE

💡 这就是为什么 “不要反序列化不可信数据” 是 Java 安全的黄金法则!

http://www.dtcms.com/a/603228.html

相关文章:

  • 深圳html5网站推广价格网站建设台州
  • 自己做一个网站难么手机怎么创建网页链接
  • 微网站如何做推广方案wordpress 引流
  • 网站设置关于我们怎么做网站建设业务员
  • MATLAB基于一阶预测有效度的IGOWLA算子模糊组合预测方法
  • 花都网站开发哈尔滨营销网站制作
  • 旅游类网站建设传媒网站建设价格
  • 呼和浩特做网站的公司有哪些个人如何免费建网站
  • 广东睿营建设有限公司网站加快网站速度
  • 丽水市建设局网站网站建设与管理试卷
  • 绿色主色调的网站wordpress 网站名称
  • Facebook矩阵引流:从防封到规模化运营的完整策略
  • 网站首页做跳转wordpress删除导入xml
  • 黄村网站建设一条龙浏览器主页网址推荐
  • 哪个网站可以做免费宣传电子商城网站设计公司哪个好
  • vue is做的购物网站seo查询官网
  • 景德镇做网站天津定制网站建设商店设计
  • Zigbee2MQTT + Home Assistant 集成商业化应用:2025年AIoT平台最佳应用
  • 免费域名网站php做网站公司哪家正规
  • 网站快照优化公司python做的大型网站
  • 字符串字符匹配
  • AJAX工具——Apifox 初学者教程
  • 易语言exe反编译成源码 | 探讨易语言反编译的原理与应用
  • 自己可以申请网站做外卖吗软件开发网站
  • 网站域名要怎样规划建站需求
  • ctfshow web221
  • day11 鹏哥C语言-指针
  • 做网站网页文件wordpress未收到验证码
  • 组件复用的 3 种高级方案:抽离逻辑 vs 封装组件 vs 自定义 hooks
  • 宣传的网站开发需要多少钱怎样把一个网站建设的更好