Java Kryo序列化

介绍

Kryo 是一个快速、高效的 Java 序列化框架,专为性能优化设计,比 JDK 原生序列化快 5-10 倍,生成的二进制数据体积更小。它支持对象图序列化(包括循环引用)、类注册(提升性能)和自定义序列化逻辑,广泛应用于游戏、大数据、分布式缓存等高性能场景。

适用场景

  • 大数据计算:Spark/Flink 分布式计算中的对象序列化(替代 JDK 原生提升性能)。
  • 游戏开发:游戏服务器间的对象传输(高性能、小体积)。
  • 分布式缓存:Redis/Memcached 存储 Java 对象(比 JSON 更高效)。
  • RPC 框架:高性能 RPC 通信(如 KryoNet)。

核心特性

  • 高性能:基于字节码生成和优化的序列化算法,速度远超 JDK 原生。
  • 体积小:生成的二进制数据比 JDK 序列化小 30%-50%。
  • 支持复杂对象:处理循环引用、深对象图、集合、枚举等复杂结构。
  • 类注册:可选的类注册机制(通过整数 ID 替代类名),进一步提升性能和减小体积。
  • 可扩展性:支持自定义序列化器(Serializer),适配特殊类型。
  • 兼容性:支持跨 JVM 版本序列化/反序列化(需注意类结构兼容性)。

底层实现原理

Kryo 的高性能源于以下核心设计:

  • 字节码生成:通过动态生成字节码(而非反射)序列化对象,减少反射开销。
  • 类注册机制:将类映射为整数 ID,序列化时仅存储 ID(而非完整类名),减小数据体积。
  • 对象引用跟踪:通过引用表处理循环引用,避免栈溢出和重复序列化。
  • 优化的基本类型处理:直接写入基本类型(如 int、long)的二进制值,无需包装。

依赖

<!-- Kryo 核心依赖 -->
<dependency>
    <groupId>com.esotericsoftware</groupId>
    <artifactId>kryo</artifactId>
    <version>5.5.0</version> <!-- 推荐使用最新稳定版 -->
</dependency>

例子

简单序列化/反序列化

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import java.io.FileInputStream;
import java.io.FileOutputStream;

// 自定义类(无需实现 Serializable 接口)
class User {
    private String name;
    private int age;
    private transient String password; // transient 字段默认不序列化

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{name='" + name + "', age=" + age + "}";
    }
}

public class KryoBasicDemo {
    public static void main(String[] args) throws Exception {
        // 1. 创建 Kryo 实例
        Kryo kryo = new Kryo();
        kryo.register(User.class); // 注册类(可选,提升性能)

        // 2. 序列化对象到文件
        try (Output output = new Output(new FileOutputStream("user.kryo"))) {
            User user = new User("张三", 25);
            kryo.writeObject(output, user);
        }

        // 3. 从文件反序列化
        try (Input input = new Input(new FileInputStream("user.kryo"))) {
            User deserializedUser = kryo.readObject(input, User.class);
            System.out.println(deserializedUser); // 输出 User{name='张三', age=25}
        }
    }
}

自定义序列化器

import com.esotericsoftware.kryo.Serializer;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;

// 自定义序列化器
class UserSerializer extends Serializer<User> {
    @Override
    public void write(Kryo kryo, Output output, User user) {
        output.writeString(user.name);
        output.writeInt(user.age * 2); // 加密年龄
    }

    @Override
    public User read(Kryo kryo, Input input, Class<User> type) {
        String name = input.readString();
        int age = input.readInt() / 2; // 解密年龄
        return new User(name, age);
    }
}

public class KryoCustomSerializerDemo {
    public static void main(String[] args) {
        Kryo kryo = new Kryo();
        kryo.register(User.class, new UserSerializer()); // 注册自定义序列化器

        Output output = new Output(1024);
        kryo.writeObject(output, new User("李四", 30));

        Input input = new Input(output.getBuffer());
        User user = kryo.readObject(input, User.class);
        System.out.println(user); // 输出 User{name='李四', age=30}
    }
}

关键配置与优化

配置项 作用
kryo.register(Class) 注册类,用整数 ID 替代类名,提升性能和减小体积。
kryo.setReferences(true) 启用引用跟踪,处理循环引用(默认开启)。
kryo.setRegistrationRequired(true) 强制类注册(避免未注册类的性能损耗,推荐生产环境使用)。
kryo.addDefaultSerializer(Class, Serializer) 为指定类设置默认序列化器。

与其他序列化方案对比

特性 Kryo JDK 原生 Protobuf
速度 极快 慢 快
体积 小 大 极小
跨语言 否(仅 Java) 否 是
循环引用支持 是 是 否
类注册 支持(可选) 不支持 支持(必须)

总结

  • 核心定位:Kryo 是 Java 专用的高性能序列化框架,专注于速度和体积优化。
  • 核心优势:比 JDK 原生快数倍,支持复杂对象和循环引用,可自定义序列化逻辑。
  • 最佳实践:
    1. 生产环境建议注册类并设置 setRegistrationRequired(true),提升性能和安全性。
    2. 处理循环引用时确保 setReferences(true)(默认开启)。
    3. 对特殊类型(如日期、集合)使用自定义序列化器优化性能。
  • 适用场景:Java 内部高性能序列化需求(大数据、游戏、缓存),跨语言场景需选 Protobuf/Avro。

简单来说,Kryo 是 Java 序列化的“性能王者”,是追求极致性能场景的首选。


原文出处:/show_1GW2JE5OXegc.html