1. 概述
Kryo 是一个专注于高性能、高效率的 Java 序列化框架,同时提供了简洁易用的 API。
本文将深入探讨 Kryo 框架的核心特性,并通过实际代码示例展示其强大功能。
2. Maven 依赖
首先需要在 pom.xml
中添加 Kryo 依赖:
<dependency>
<groupId>com.esotericsoftware</groupId>
<artifactId>kryo</artifactId>
<version>4.0.1</version>
</dependency>
最新版本可在 Maven Central 查询。
3. Kryo 基础
让我们先了解 Kryo 的工作原理,以及如何用它进行对象序列化和反序列化。
3.1 核心机制
框架的核心是 Kryo
类,它是所有功能的入口点。该类负责:
- ✅ 协调整个序列化流程
- ✅ 将类映射到
Serializer
实例 - ✅ 通过
Serializer
将对象图转换为字节流
序列化后的字节通过 Output
对象写入流,可存储到文件、数据库或网络传输。反序列化时,使用 Input
对象读取字节并解码为 Java 对象。
3.2 对象序列化
先创建测试初始化方法:
@Before
public void init() {
kryo = new Kryo();
output = new Output(new FileOutputStream("file.dat"));
input = new Input(new FileInputStream("file.dat"));
}
单对象序列化简单粗暴:
@Test
public void givenObject_whenSerializing_thenReadCorrectly() {
Object someObject = "Some string";
kryo.writeClassAndObject(output, someObject);
output.close();
Object theObject = kryo.readClassAndObject(input);
input.close();
assertEquals(theObject, "Some string");
}
⚠️ 注意:必须调用 close()
方法,因为 Output
和 Input
分别继承自 OutputStream
和 InputStream
。
多对象序列化同样简单:
@Test
public void givenObjects_whenSerializing_thenReadCorrectly() {
String someString = "Multiple Objects";
Date someDate = new Date(915170400000L);
kryo.writeObject(output, someString);
kryo.writeObject(output, someDate);
output.close();
String readString = kryo.readObject(input, String.class);
Date readDate = kryo.readObject(input, Date.class);
input.close();
assertEquals(readString, "Multiple Objects");
assertEquals(readDate.getTime(), 915170400000L);
}
✅ 优势:通过指定 readObject()
的目标类,避免了类型转换。
4. 序列化器
本节介绍 Kryo 内置的序列化器,以及如何自定义序列化器。
4.1 默认序列化器
Kryo 序列化对象时,会自动创建已注册的 Serializer
实例。这些默认序列化器无需额外配置即可使用。
框架内置了处理以下类型的序列化器:
- ✅ 基本数据类型
- ✅ 集合(List/Map)
- ✅ 枚举
- ✅ 其他常见类型
当找不到匹配的序列化器时,Kryo 会使用 FieldSerializer
,它能处理几乎所有类型的对象。
示例: 创建 Person
类:
public class Person {
private String name = "John Doe";
private int age = 18;
private Date birthDate = new Date(933191282821L);
// 标准构造器、getter和setter
}
直接序列化 Person
对象:
@Test
public void givenPerson_whenSerializing_thenReadCorrectly() {
Person person = new Person();
kryo.writeObject(output, person);
output.close();
Person readPerson = kryo.readObject(input, Person.class);
input.close();
assertEquals(readPerson.getName(), "John Doe");
}
✅ 无需任何配置,Kryo 自动为 Person
生成了 FieldSerializer
。
4.2 自定义序列化器
当需要更精细的控制时,有两种方案:
- 创建自定义
Serializer
类 - 让类自身实现序列化逻辑
方案一:自定义序列化器类
public class PersonSerializer extends Serializer<Person> {
public void write(Kryo kryo, Output output, Person object) {
output.writeString(object.getName());
output.writeLong(object.getBirthDate().getTime());
}
public Person read(Kryo kryo, Input input, Class<Person> type) {
Person person = new Person();
person.setName(input.readString());
long birthDate = input.readLong();
person.setBirthDate(new Date(birthDate));
person.setAge(calculateAge(birthDate));
return person;
}
private int calculateAge(long birthDate) {
// 自定义计算逻辑
return 18;
}
}
测试自定义序列化器:
@Test
public void givenPerson_whenUsingCustomSerializer_thenReadCorrectly() {
Person person = new Person();
person.setAge(0); // 初始值会被覆盖
kryo.register(Person.class, new PersonSerializer());
kryo.writeObject(output, person);
output.close();
Person readPerson = kryo.readObject(input, Person.class);
input.close();
assertEquals(readPerson.getName(), "John Doe");
assertEquals(readPerson.getAge(), 18); // 验证自定义逻辑生效
}
✅ 使用 @DefaultSerializer
注解可避免手动注册:
@DefaultSerializer(PersonSerializer.class)
public class Person implements KryoSerializable {
// ...
}
方案二:实现 KryoSerializable
接口
public class Person implements KryoSerializable {
// ...
public void write(Kryo kryo, Output output) {
output.writeString(name);
// 其他字段...
}
public void read(Kryo kryo, Input input) {
name = input.readString();
// 其他字段...
}
}
4.3 Java 序列化器
极少数情况下 Kryo 无法序列化某个类时,可回退到标准 Java 序列化机制:
- 类需实现
Serializable
接口 - 使用
JavaSerializer
处理
示例:
public class ComplexObject implements Serializable {
private String name = "Bael";
// 标准getter和setter
}
@Test
public void givenJavaSerializable_whenSerializing_thenReadCorrectly() {
ComplexClass complexObject = new ComplexClass();
kryo.register(ComplexClass.class, new JavaSerializer());
kryo.writeObject(output, complexObject);
output.close();
ComplexClass readComplexObject = kryo.readObject(input, ComplexClass.class);
input.close();
assertEquals(readComplexObject.getName(), "Bael");
}
⚠️ 踩坑提示:Java 序列化性能较差,仅作为最后备选方案。
5. 总结
本文深入探讨了 Kryo 框架的核心特性:
- ✅ 序列化多种简单对象
- ✅ 使用
FieldSerializer
处理自定义类 - ✅ 创建自定义序列化器
- ✅ 回退到 Java 标准序列化机制
完整源代码可在 GitHub 获取。