序列化与反序列化

共 23 题
📑 题目列表 23 题
#
★★★

1. Externalizable 与 Serializable 的差异

Externalizable 与 Serializable 的差异是什么?各自如何选择?

  • Externalizable 与 Serializable 接口
  • 序列化机制差异
  • 性能与灵活度

Serializable 是标记接口,序列化机制由 JVM 自动完成(反射遍历字段),开发者可自定义 writeObject/readObject 控制,但默认会序列化所有非 transient 字段;实现简单但性能较差(反射开销、元数据完整)。Externalizable 接口定义 writeExternal/readExternal 两个方法,开发者需完全手动实现序列化逻辑,只序列化需要字段,性能更好、更可控,但需要开发者手动管理所有字段。差异:Serializable 自动、反射、字段完整、实现简单;Externalizable 手动、精确、性能好、灵活。选择:简单对象用 Serializable;需要高性能、精确控制(如只序列化部分字段、定制格式)用 Externalizable。理解两者差异(自动 vs 手动、性能与控制)是本题关键。

核心是 Serializable 自动反射序列化、Externalizable 手动精确控制,性能与灵活度不同。理解差异与选择是本题关键。

#
★★★

2. Hessian/Protobuf/Avro 等跨语言序列化框架在微服务中的工程取舍

Hessian/Protobuf/Avro 等跨语言序列化框架在微服务中的工程取舍是什么?

  • 各序列化框架的特点
  • 跨语言兼容性
  • 工程取舍

Hessian、Protobuf、Avro 都是跨语言序列化框架,取舍不同:Protobuf 二进制紧凑、性能高、schema 强类型、工具链完善(proto 编译),适合高性能、跨语言、schema 稳定的 RPC(如 gRPC);Avro 基于 schema 且 schema 随数据存储(JSON schema),适合 Hadoop 生态、大数据场景、schema 演进(冷热数据);Hessian 是 Java 生态的二进制序列化,跨语言支持较弱,性能一般,适合轻量 RPC(如 Dubbo 早期)。工程取舍:考虑性能(Protobuf 优)、跨语言支持(Protobuf/Avro 优)、schema 管理(Avro 与 Protobuf 强 schema)、生态(微服务选 Protobuf/gRPC,大数据选 Avro)、Java 轻量(Hessian)。还需考虑可读性、体积、版本演进。理解各框架特点与按场景取舍是本题关键。

核心是 Protobuf 强类型高性能适合 RPC、Avro schema 随数据适合大数据、Hessian 轻量 Java 生态,按场景取舍。理解取舍是本题关键。

#
★★★

3. JDK 内置序列化(Serializable)的安全风险与 Jackson/Kryo 等替代方案的取舍

JDK 内置序列化(Serializable)的安全风险有哪些?与 Jackson/Kryo 等替代方案的取舍是什么?

  • 内置序列化的安全风险
  • 反序列化漏洞
  • 替代方案取舍

JDK 内置序列化(Serializable)的安全风险:反序列化攻击(反序列化恶意数据可触发任意代码执行,如 gadget chain)、反序列化时执行构造函数/readObject 的风险、对象图过大导致 DoS、版本兼容问题。历史上 RMI、攻击链利用 Java 序列化已造成大量 CVE。替代方案取舍:Jackson(JSON,文本可读、跨语言、安全但需防多态反序列化)、Kryo(二进制、性能高、但需注册类、有安全风险需配置)、Protobuf(强类型、安全、无反射 gadget)。取舍:避免使用 JDK 内置序列化作为对外协议,改用 JSON/Protobuf/自定义二进制;若必须用,用 ObjectInputFilter 白名单过滤、限制类。理解内置序列化安全风险与替代方案(JSON/Protobuf/Kryo)的取舍是本题关键。

核心是内置序列化有反序列化攻击风险,应改用 JSON/Protobuf/Kryo 等并配合过滤。理解风险与取舍是本题关键。

#
★★★

4. Java 原生序列化(Serializable)的机制与 serialVersionUID

Java 原生序列化(Serializable)的机制是什么?serialVersionUID 的作用是什么?

  • Serializable 的序列化机制
  • serialVersionUID 的作用
  • 版本兼容

Java 原生序列化通过 Serializable 接口,序列化时 JVM 根据类结构(字段、类型)写出对象图,包括类描述(类名、serialVersionUID、字段)、对象数据;反序列化时按类描述重建对象。serialVersionUID 是类的版本标识,用于验证序列化与反序列化时类是否兼容:若 serialVersionUID 不一致,反序列化抛 InvalidClassException。建议显式声明 serialVersionUID(private static final long serialVersionUID = 1L),避免依赖 JVM 自动生成(基于类结构,结构变化会变)。机制要点:非 transient 字段被序列化,static 不序列化,transient 需自定义处理;对象图自动处理循环引用。理解 Serializable 机制(类描述+字段)与 serialVersionUID 版本验证作用、显式声明最佳实践是本题关键。

核心是序列化按类描述写出、serialVersionUID 验证版本兼容、显式声明避免自动生成变化。理解机制与版本是本题关键。

#
★★★

5. Serializable 的安全性与反序列化攻击

Serializable 的安全性如何?反序列化攻击是什么?

  • Serializable 的安全风险
  • 反序列化攻击原理
  • 防护措施

Serializable 的安全性存在重大风险,核心是反序列化攻击(Deserialization Attack):反序列化时,JVM 会创建对象并调用 readObject/构造函数,若攻击者构造恶意序列化数据,可通过 gadget chain(利用应用及依赖库中存在 readObject 中触发危险操作的类,如 TemplatesImpl、InvokerTransformer)在反序列化时执行任意代码(RCE)。Java 序列化是"黑盒"格式,攻击者难以追踪数据。防护措施:避免反序列化不可信数据;使用 ObjectInputFilter 设置类白名单/黑名单(JEP 290);优先使用 JSON/Protobuf 等安全格式;升级依赖库(消除已知 gadget);部署时禁用不必要的外向序列化入口(如 RMI)。理解反序列化攻击原理(gadget chain 触发 RCE)与防护(过滤、避免不可信数据、安全格式)是本题关键。

核心是反序列化攻击通过 gadget chain 在反序列化时触发 RCE,防护靠过滤、避免不可信数据、安全格式。理解原理与防护是本题关键。

#
★★★

6. JDK 17 序列化过滤器(ObjectInputFilter)的工程应用

JDK 17 序列化过滤器(ObjectInputFilter)的工程应用是什么?

  • ObjectInputFilter 过滤机制
  • 白名单/黑名单
  • 工程应用

ObjectInputFilter(JEP 290,JDK 9 引入,JDK 17 完善)用于反序列化时过滤类,防止反序列化攻击。它通过 ObjectInputFilter.Config 设置全局过滤器,或通过 ObjectInputStream.setObjectInputFilter 设置,过滤规则可基于类名、包名、深度、数组长度、引用数等。工程应用:设置类白名单(只允许反序列化信任的类),拒绝危险类(如 gadget 类);限制对象图大小(深度、数量)防 DoS;结合日志记录被拒绝的类用于安全分析。现代实践:在反序列化入口(如 RMI、自定义协议)设置 ObjectInputFilter,白名单机制是 JEP 290 的核心价值。理解 ObjectInputFilter 的过滤机制(类名/深度/数量)与白名单工程应用是本题关键。

核心是 ObjectInputFilter 按类名/深度/数量过滤反序列化,白名单防攻击,工程应用在反序列化入口。理解机制与应用是本题关键。

#
★★

7. JDK 内部对象(BigInteger 等)的序列化兼容性

JDK 内部对象(如 BigInteger 等)的序列化兼容性如何?

  • JDK 内部对象的序列化
  • 版本兼容性
  • 注意事项

JDK 内部对象(如 BigInteger、BigDecimal、Date、集合类等)实现了 Serializable,可被序列化。这些类的序列化兼容性由 JDK 保证(它们的 serialVersionUID 固定),但注意:某些内部类、lambda、匿名类、非 Serializable 的底层对象不可序列化;JDK 内部对象的序列化格式是 JDK 内部实现,跨 JDK 版本可能有变化,但 Data 等核心类型保持稳定。BigInteger 等不可变对象序列化后跨版本兼容性较好。注意事项:不要依赖 JDK 内部类的序列化格式作为长期协议(内部实现可能变);序列化含 JDK 内部对象图时注意对象大小与安全。理解 JDK 内部对象(BigInteger 等)序列化兼容性由 JDK 保证、但不宜作为长期协议是本题关键。

核心是 JDK 内部对象实现 Serializable 且有兼容性保证,但内部格式不宜作为长期协议。理解兼容性与注意事项是本题关键。

#
★★

8. JDK 序列化与 JMS Message 序列化

JDK 序列化与 JMS Message 序列化有什么关系?JMS 如何序列化消息?

  • JMS Message 的类型
  • ObjectMessage 的序列化
  • 与 JDK 序列化的关系

JMS(Java Message Service)消息有多种类型(TextMessage、BytesMessage、ObjectMessage、MapMessage 等)。ObjectMessage 使用 JDK 序列化(对象实现 Serializable)将 Java 对象序列化为消息体,因此 ObjectMessage 的序列化依赖 JDK 内置序列化,存在反序列化安全风险。生产实践中,JMS 消息通常优先用 TextMessage/BytesMessage(如 JSON、二进制),避免 ObjectMessage 的安全风险与版本耦合。TextMessage 传字符串(可携带 JSON),BytesMessage 传字节。理解 ObjectMessage 基于 JDK 序列化、存在安全风险,实践优先 Text/Bytes 消息是本题关键。

核心是 ObjectMessage 用 JDK 序列化存在反序列化风险,实践优先 Text/Bytes 消息。理解关系与风险是本题关键。

#
★★

9. JDK 序列化与 RMI 协议

JDK 序列化与 RMI 协议的关系是什么?RMI 如何传输参数?

  • RMI 基于 JDK 序列化
  • RMI 参数传输
  • 安全风险

RMI(Java Remote Method Invocation)使用 JDK 内置序列化在客户端与服务器之间传输远程方法调用的参数、返回值与异常。远程方法的参数对象必须实现 Serializable,通过 ObjectOutputStream 序列化后经网络传输,服务端用 ObjectInputStream 反序列化。因此 RMI 深度依赖 JDK 序列化,具有反序列化安全风险(攻击者可通过 RMI 端口反序列化恶意数据)。RMI 的序列化还涉及远程引用(RemoteRef)、Registry 等。安全实践:RMI 仅用于可信内网,限制端口暴露,配置 ObjectInputFilter,或用其他 RPC 框架(如 gRPC)替代。理解 RMI 基于 JDK 序列化传输参数、存在反序列化风险是本题关键。

核心是 RMI 用 JDK 序列化传输参数/返回值,存在反序列化攻击风险,应限制暴露。理解关系与风险是本题关键。

#
★★

10. Jackson 多态反序列化(@JsonTypeInfo/defaultTyping)的安全边界与已知漏洞(CVE)

Jackson 多态反序列化(@JsonTypeInfo/defaultTyping)的安全边界与已知漏洞(CVE)是什么?

  • Jackson 多态反序列化
  • defaultTyping 的安全风险
  • 已知 CVE 与防护

Jackson 的多态反序列化通过 @JsonTypeInfo 或 ObjectMapper.enableDefaultTyping 将类型信息写入 JSON,反序列化时按类型创建对象。这带来安全风险:攻击者可通过 JSON 中的类型字段指定危险类(如 com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl 等 gadget),触发反序列化攻击(RCE)。历史上存在大量 Jackson 相关 CVE(如 CVE-2017-7525、CVE-2019-12384 等),都是通过 defaultTyping 或 @JsonTypeInfo 的多态反序列化利用 gadget。安全边界:禁用 defaultTyping(默认不启用);若需多态,用 @JsonTypeInfo 白名单(@JsonSubTypes 限定合法子类)或自定义反序列化器限制类;升级 Jackson 版本修复已知 CVE;配置 TypeResolverBuilder 白名单。理解 Jackson 多态反序列化的安全风险(类型注入)与防护(默认禁用、白名单、升级)是本题关键。

核心是 Jackson 多态反序列化可通过类型字段注入 gadget 导致 RCE,历史有大量 CVE,防护靠禁用 defaultTyping、白名单、升级。理解风险与防护是本题关键。

#
★★

11. Kryo 的 FieldSerializer 在对象图循环引用检测与性能特征

Kryo 的 FieldSerializer 在对象图循环引用检测与性能特征如何?

  • Kryo FieldSerializer
  • 循环引用检测
  • 性能特征

Kryo 的 FieldSerializer 是默认的字段序列化器,直接访问对象字段(可反射或 Unsafe)进行序列化,性能高于 JDK 序列化。Kryo 支持循环引用检测:通过内部引用表(reference)跟踪已序列化对象,当对象再次出现时写入引用而非重复序列化,从而处理循环引用(如 A <-> B)并避免死循环。性能特征:Kryo 二进制紧凑、速度快,但性能受序列化器选择、对象图规模、是否注册类影响。循环引用检测有开销(维护引用表),若对象图无循环且对象量大,可关闭引用检测(kryo.setReferences(false))提升性能。理解 FieldSerializer 直接字段访问、循环引用检测(引用表)与性能权衡(引用检测开销)是本题关键。

核心是 FieldSerializer 直接访问字段、循环引用用引用表处理、无循环时可关闭引用提升性能。理解检测与性能是本题关键。

#
★★

12. Kryo 相比 JDK 序列化的性能优势与限制(类注册/版本兼容/安全),适用场景如何界定?

Kryo 相比 JDK 序列化的性能优势与限制有哪些?适用场景如何界定?

  • Kryo 的性能优势
  • 类注册/版本兼容/安全限制
  • 适用场景

Kryo 相比 JDK 序列化性能优势:二进制紧凑、直接字段访问、速度快、体积小(无需完整类描述)。限制:需要注册类(注册后以 ID 引用,更紧凑但需维护注册表,未注册类会抛异常或需开启非注册支持);版本兼容需手动管理(字段增删需兼容策略,如 Kryo 的 FieldSerializer 对字段变化敏感);安全性(Kryo 反序列化可构造任意类,需配置白名单/限制,避免 gadget)。适用场景:高性能、低延迟、体积敏感的 Java 内部通信(如缓存、RPC 内部协议),类固定且版本可控;不适合跨语言、不可信数据、频繁 schema 演进。理解 Kryo 性能优势(紧凑快速)与限制(类注册/版本/安全)及适用场景(Java 内部高性能)是本题关键。

核心是 Kryo 紧凑快速但需类注册、版本敏感、有安全风险,适合 Java 内部高性能场景。理解优劣与场景是本题关键。

#
★★

13. ObjectInputStream/ObjectOutputStream 的 writeObject/readObject 自定义序列化与 readResolve 单例保护

ObjectInputStream/ObjectOutputStream 的 writeObject/readObject 自定义序列化与 readResolve 单例保护各自如何工作?

  • writeObject/readObject 自定义
  • readResolve 单例保护
  • 序列化定制的机制

ObjectOutputStream.writeObject 与 ObjectInputStream.readObject 是序列化入口。若类自定义 writeObject/readObject 方法,序列化框架会调用它们以定制序列化流程(如控制字段、加密、压缩)。readResolve() 方法在反序列化完成后被调用,返回值替换反序列化得到的对象,用于单例保护与特殊对象替换(如枚举、单例)。单例保护:若单例类实现 readResolve 返回已存在的单例实例,则反序列化不会创建新实例,保证单例不被破坏。writeReplace() 在序列化前被调用,返回替代对象。理解 writeObject/readObject 定制序列化、readResolve 单例保护与 writeReplace 替换是本题关键。

核心是 writeObject/readObject 定制序列化、readResolve 返回替换对象保护单例、writeReplace 序列化前替换。理解机制是本题关键。

private Object readResolve() {
    return INSTANCE;   // 返回单例,反序列化不破坏单例
}
#
★★

14. Protobuf(com.google.protobuf)的工程实践

Protobuf(com.google.protobuf)的工程实践是什么?

  • Protobuf 的工程使用
  • 生成代码与 schema
  • 工程实践要点

Protobuf(com.google.protobuf)是 Google 的二进制序列化协议,工程实践:定义 .proto schema,用 protoc 编译器生成 Java 代码(Message 类、Builder);使用 Builder 构建对象、parseFrom/toByteArray 序列化;字段有编号与类型,支持嵌套、repeated、enum、oneof;向前/向后兼容(字段编号不删改、新增字段不破坏旧数据)。工程实践要点:schema 版本管理(字段编号稳定)、避免破坏性变更、用 gRPC 集成、性能优化(复用 builder、避免重复解析)、schema 评审。Protobuf 生成代码不可变(Immutable),线程安全。理解 Protobuf 的 schema 编译、Builder 构建、序列化与版本兼容实践是本题关键。

核心是 Protobuf 用 .proto 编译生成代码、Builder 构建、序列化配合 gRPC,版本兼容靠字段编号稳定。理解工程实践是本题关键。

#
★★

15. Unshared 序列化与对象共享

Unshared 序列化与对象共享是什么?writeUnshared/readUnshared 的作用是什么?

  • 对象共享与引用
  • writeUnshared/readUnshared
  • 序列化语义

序列化默认支持对象共享:同一对象在对象图中多次出现时,只序列化一次,后续通过引用(handle)恢复,从而保持对象引用关系(如两个字段指向同一对象,反序列化后仍指向同一对象)。writeUnshared/readUnshared 用于"非共享"序列化:writeUnshared 写入对象时不记录引用(每次独立写入),readUnshared 读取时总是创建新对象(不解析已有引用)。用途:当需要避免对象共享(如每次反序列化得到新实例)、防止引用解析(如安全边界)时使用。注意 readUnshared 读取一个被共享引用的对象会抛异常。理解默认共享(引用保持)、writeUnshared/readUnshared 非共享语义是本题关键。

核心是默认序列化共享对象引用,writeUnshared/readUnshared 非共享每次独立。理解共享与 Unshared 语义是本题关键。

#
★★

16. serialVersionUID 在版本兼容性中的作用与显式声明的最佳实践

serialVersionUID 在版本兼容性中的作用与显式声明的最佳实践是什么?

  • serialVersionUID 的版本验证
  • 显式声明的重要性
  • 兼容性最佳实践

serialVersionUID 用于验证序列化与反序列化时类的版本兼容性:反序列化时若数据中的 serialVersionUID 与当前类不一致,抛 InvalidClassException。作用:防止类结构变化导致反序列化错误。最佳实践:显式声明 serialVersionUID(private static final long serialVersionUID),避免依赖 JVM 自动生成(自动生成基于类结构,类结构变化会改变 UID,导致兼容问题);显式声明后可控制版本,兼容性变更不改变 UID。兼容性变更(如新增字段)在默认值下可反序列化旧数据;不兼容变更(删除字段)需处理。理解 serialVersionUID 的版本验证作用与显式声明最佳实践是本题关键。

核心是 serialVersionUID 验证版本兼容,显式声明避免自动生成变化,控制兼容性。理解作用与最佳实践是本题关键。

#
★★

17. 记录类(record)的 JDK 14+ 自动序列化支持与传统类的差异

记录类(record)的 JDK 14+ 自动序列化支持与传统类的差异是什么?

  • record 的自动序列化
  • 与传统类的差异
  • 序列化语义

record 类(JDK 14+ 引入,JDK 16 正式)实现了 Serializable 时,序列化基于其组件(record components)自动生成 writeObject/readObject(或直接序列化组件),反序列化通过 canonical constructor 重建,保证组件不变性。与传统类的差异:record 的序列化只序列化组件(不可变性),不序列化派生字段;反序列化用 canonical constructor 而非默认构造函数,保证 record 的约束(不可变、组件一致);record 天然适合作为值对象序列化。注意:record 的序列化格式基于组件,新增/删除组件会影响兼容性。理解 record 自动序列化组件、经 canonical constructor 重建、与传统类的差异是本题关键。

核心是 record 只序列化组件、经 canonical constructor 重建保持不可变,与传统类差异明确。理解差异是本题关键。

#
★★

18. 跨语言的序列化(JSON/Protobuf/Avro)选型

跨语言的序列化(JSON/Protobuf/Avro)选型如何考虑?

  • JSON/Protobuf/Avro 特点
  • 跨语言选型
  • 场景权衡

跨语言序列化选型需权衡:JSON 文本可读、跨语言广泛支持、动态、但体积大、性能一般、无强类型 schema;Protobuf 二进制紧凑、性能高、强类型 schema、跨语言、适合 RPC 与高吞吐;Avro 基于 schema(schema 随数据存储)、适合大数据生态(Hadoop)、schema 演进好。选型考虑:性能与体积(Protobuf 优)、schema 管理与演进(Avro/Protobuf 强)、可读性与调试(JSON)、生态(大数据选 Avro、RPC 选 Protobuf/gRPC、Web 选 JSON)、跨语言支持(三者都支持)。需要强类型与高性能选 Protobuf,需要 schema 演进与大数据选 Avro,需要可读动态选 JSON。理解各格式特点与按场景(性能/schema/可读/生态)选型是本题关键。

核心是 JSON 可读动态、Protobuf 强类型高性能、Avro schema 随数据适合大数据,按场景选型。理解选型是本题关键。

#

19. Fastjson autoType 反序列化漏洞历史与 safeMode 防护(关闭 autoType 的白名单机制)

Fastjson autoType 反序列化漏洞的历史与 safeMode 防护(关闭 autoType 的白名单机制)是什么?

  • Fastjson autoType 漏洞
  • safeMode 防护
  • 白名单机制

Fastjson 的 autoType 特性允许在 JSON 中通过 @type 指定反序列化类,历史上被利用产生大量反序列化漏洞(如 RCE),攻击者通过指定 gadget 类触发任意代码执行。Fastjson 多次修复又多次被绕过(如黑名单绕过)。safeMode 防护:Fastjson 的 safeMode(或全局配置)关闭 autoType,只允许白名单类反序列化,从而杜绝通过 @type 注入危险类。白名单机制:通过 ParserConfig.addAccept 或 safemode 默认只接受必要类,显式配置允许的类。最佳实践:关闭 autoType(safeMode),使用白名单;或改用 Jackson/Protobuf 等安全序列化。理解 Fastjson autoType 漏洞(@type 注入 gadget)与 safeMode 白名单防护是本题关键。

核心是 Fastjson autoType 通过 @type 注入 gadget 导致 RCE,safeMode 关闭 autoType 用白名单防护。理解漏洞与防护是本题关键。

#

20. JDK 24+ 序列化移除 SecurityManager 相关路径(JEP 486 永久禁用)

JDK 24+ 序列化移除 SecurityManager 相关路径(JEP 486 永久禁用)是什么?

  • JEP 486
  • SecurityManager 移除
  • 序列化路径影响

JEP 486 永久禁用 SecurityManager(JDK 24 默认禁用,后续移除),SecurityManager 是 Java 的安全沙箱机制,已因时代原因被弃用。序列化相关路径受影响:序列化/反序列化中依赖 SecurityManager 做权限检查的代码(如 ObjectInputStream 的 AccessController 检查)被移除,改为基于模块与 ObjectInputFilter 的安全机制。开发者在序列化场景应放弃依赖 SecurityManager,改用 ObjectInputFilter、模块封装等现代安全手段。理解 JEP 486 移除 SecurityManager、序列化路径改用 ObjectInputFilter 等现代机制是本题关键。

核心是 JEP 486 永久禁用 SecurityManager,序列化安全改用 ObjectInputFilter 与模块机制。理解变更与影响是本题关键。

#

21. JDK 25 中 ObjectInputFilter 在反序列化黑白名单与 JEP 290 的工程价值

JDK 25 中 ObjectInputFilter 在反序列化黑白名单与 JEP 290 的工程价值是什么?

  • ObjectInputFilter 黑白名单
  • JEP 290
  • 工程价值

JEP 290(JDK 9)引入 ObjectInputFilter,用于反序列化过滤,JDK 25 中持续完善。ObjectInputFilter 可设置白名单(只允许指定类/包)与黑名单(拒绝危险类),并限制深度、引用数、数组长度等,防止反序列化攻击与 DoS。工程价值:在反序列化入口(RMI、自定义协议、ObjectInputStream)设置过滤器,白名单允许信任类,黑名单拒绝已知 gadget 类;限制对象图规模防 DoS;配合日志记录被拒绝的类。JDK 25 中 ObjectInputFilter 是反序列化安全的核心防线,工程上应积极配置。理解 ObjectInputFilter 黑白名单、JEP 290 与反序列化安全工程价值是本题关键。

核心是 JEP 290 的 ObjectInputFilter 用黑白名单与规模限制防反序列化攻击,是核心安全防线。理解工程价值是本题关键。

#

22. JDK 25 中 readObject/writeObject 在反序列化攻击(Deserialization Attack)下的防护

JDK 25 中 readObject/writeObject 在反序列化攻击下的防护是什么?

  • readObject/writeObject 的定制
  • 反序列化防护
  • 安全实践

在 JDK 25 中,readObject/writeObject 是自定义序列化方法,反序列化时 readObject 会被调用,攻击者可能通过构造恶意数据触发 readObject 中的危险操作(gadget)。防护措施:readObject 中严格校验反序列化数据的合法性(如类型、范围、数量),避免在 readObject 中执行危险操作;对不可信数据使用 ObjectInputFilter 白名单过滤;优先使用 record 等安全序列化;避免反序列化不可信数据。writeObject 在序列化时校验数据并只写必要字段。理解 readObject 的风险(恶意数据触发)与防护(校验、过滤、安全序列化)是本题关键。

核心是 readObject 可能被恶意数据触发风险,防护靠校验、ObjectInputFilter、安全序列化。理解防护是本题关键。

#

23. 序列化框架性能基准方法(JMH)与对象图规模、循环引用对结果的影响

序列化框架性能基准方法(JMH)是什么?对象图规模、循环引用对结果有何影响?

  • JMH 基准测试
  • 对象图规模与循环引用
  • 性能结果影响

JMH(Java Microbenchmark Harness)是 JVM 性能基准测试框架,用于准确测量序列化性能(避免 JIT、逃逸分析等干扰)。基准方法:定义 Benchmark 方法,设置迭代次数、预热(warmup)、fork,测量序列化/反序列化的吞吐与耗时。对象图规模与循环引用对结果的影响:对象图规模越大,序列化占用越多时间与内存,测量结果反映规模敏感性;循环引用影响序列化实现(如 Kryo 需引用表、JDK 序列化用 handle),有循环引用的对象图序列化开销不同,且不同框架处理循环引用的方式不同(是否支持、开销),影响基准结果。基准时应覆盖不同对象图规模与循环引用场景,避免单一场次误导。理解 JMH 基准方法与对象图规模/循环引用对性能结果的影响是本题关键。

核心是 JMH 提供准确基准,对象图规模与循环引用影响序列化开销与框架差异,基准需覆盖场景。理解方法与影响是本题关键。