Kryo关闭引用跟踪(setReferences(false))可提升序列化性能,但仅适用于无重复或循环引用的场景;需配合显式类注册以进一步优化体积与速度。

Kryo 默认启用对象引用跟踪(references),能自动识别并处理重复引用和循环引用,避免重复序列化同一对象。但这个机制会带来额外的元数据开销(如引用ID记录)和哈希表管理成本。若业务场景中确定不存在重复引用或循环引用,关闭它就能直接规避这部分开销。
关闭引用跟踪提升性能
Kryo 通过 setReferences(false) 禁用引用跟踪后:
- 不再为每个对象写入引用标记(如
0x00表示新对象、0x01 + ID表示已见对象) - 跳过内部
ReferenceMap的查找与注册操作 - 序列化体积更小、CPU 消耗更低、速度更快
Kryo kryo = new Kryo(); kryo.setReferences(false); // 关键配置 kryo.register(User.class); kryo.register(Order.class); // 后续序列化时,相同对象实例将被多次完整写出,而非复用引用
⚠️ 注意:仅在确认对象图无共享引用时使用。例如:
- DTO 是一次性的扁平结构(如
new User().setOrders(Arrays.asList(new Order(), new Order())),两个 Order 实例不同) - 方法内构造的临时对象,未被多个字段共同持有
需要保留引用跟踪的典型场景
以下情况必须保持 setReferences(true)(默认值):
立即学习“Java免费学习笔记(深入)”;
- 对象之间存在循环依赖(如
User ↔ Department双向引用) - 多个字段指向同一个实例(如
Order中customer和createdBy指向同一User对象) - 使用了集合类中的重复元素(如
List<User>包含相同User实例两次)
否则反序列化会失败或产生多个独立对象,破坏原始语义。
结合注册进一步减少开销
即使关闭引用跟踪,仍建议显式注册类:
- 避免每次序列化都写入全限定类名(节省空间)
- 加速类型查找(跳过反射解析类名)
- 与
setReferences(false)搭配,实现“轻量无引用”模式
kryo.register(User.class, 1); kryo.register(Order.class, 2); kryo.setRegistrationRequired(true); // 强制注册,防止运行时异常
注册 ID 必须集群节点间一致,否则跨节点反序列化失败。
实际效果对比(以含 3 个相同 User 实例的 List 为例)
| 配置 | 序列化体积 | 是否复用对象 | 反序列化后对象数 |
|---|---|---|---|
setReferences(true)(默认) |
小(约 320 字节) | 是(1 个 User 实例) | 1 |
setReferences(false) |
略大(约 480 字节) | 否(3 份完整副本) | 3 |
体积增加是明确代价,换来的是确定性性能和更低延迟——尤其在高频、短生命周期的 RPC 或缓存场景中值得权衡。
不复杂但容易忽略


















