ObjectOutputStream 的 useProtocolVersion 是 protected 方法,用于指定序列化协议版本(1 或 2),需在子类中覆写 writeStreamHeader 并调用;版本 1 兼容所有 JDK,版本 2 自 JDK 1.4 起引入但旧版无法识别。

ObjectOutputStream 的 useProtocolVersion 方法用于显式指定序列化协议版本,但它本身不是 public 方法,而是受保护(protected)的,仅在自定义子类中可重写或调用。它的核心作用是控制序列化流头部写入的协议标识,从而影响反序列化端(尤其是旧版 JDK)能否正确识别和解析字节流。
协议版本值的含义与可选范围
Java 序列化协议有多个历史版本,由 ObjectStreamConstants.PROTOCOL_VERSION_1(默认值,即 1)和 PROTOCOL_VERSION_2(值为 2)定义。后者自 JDK 1.4 引入,主要优化了长字符串和大数组的编码效率,并改进了对重复对象引用的处理。JDK 1.2–1.3 仅支持版本 1;JDK 1.4 及以后默认使用版本 2,但完全兼容版本 1 的读取。
- PROTOCOL_VERSION_1:最基础格式,所有 JDK 版本均能生成和读取
-
PROTOCOL_VERSION_2:新增块数据编码、更紧凑的 UTF 编码,但 JDK 1.2/1.3 的
ObjectInputStream无法识别其头部,会抛出StreamCorruptedException
如何安全启用 useProtocolVersion
不能直接调用 oos.useProtocolVersion(...),因为它是 protected 方法。正确做法是在继承 ObjectOutputStream 的子类中覆写 writeStreamHeader(),并在其中调用 super.useProtocolVersion(...):
- 创建子类,在构造时调用
super(OutputStream),然后立即调用useProtocolVersion(PROTOCOL_VERSION_1) - 确保该子类实例在写入前未执行任何
writeObject操作(否则 header 已写入,再调用无效) - 若目标是兼容 JDK 1.2/1.3 环境,必须强制设为
PROTOCOL_VERSION_1,且避免使用 JDK 5+ 新增的序列化特性(如 enum、dynamic proxy)
旧版 JDK 兼容性关键限制
即使协议版本设为 1,仍需注意以下运行时兼容性问题:
- 类的
serialVersionUID必须显式声明且保持一致,否则 JDK 1.2–1.4 会因签名不匹配拒绝反序列化 - 不能包含 JDK 1.5+ 才引入的类型(如
java.util.concurrent.ConcurrentHashMap),旧 JVM 无对应类定义 - 静态字段、transient 字段、构造器逻辑差异不会被协议版本控制,需靠代码层面适配
验证是否生效的简单方式
序列化后查看文件前 4 字节(header)可确认协议版本:
- 版本 1:固定为
AC ED 00 01(十六进制) - 版本 2:前两字节仍是
AC ED,但第三、四字节为00 02 - 用
xxd -c 1 t.tmp | head -4或十六进制编辑器快速比对











