You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Kryo 5.6.0序列化注册类时遇UnmodifiableMap不可见问题求助

问题描述

使用Kryo 5.6.0 + Java 1.8,启用类注册序列化时触发如下异常:

com.esotericsoftware.kryo.KryoException: java.lang.IllegalArgumentException: Class is not registered: java.util.Collections$UnmodifiableMap

系统提示需执行kryo.register(java.util.Collections.UnmodifiableMap.class)注册该类,但UnmodifiableMap是Java包私有内部类,直接引用会报ClassNotFoundException。相关代码如下:

TestClass 代码

public class TestClass implements Serializable {
    private static final long serialVersionUID = 6400867639765519428L;
    private List<Books> items;
    public TestClass(List<Books> items) {
        super();
        if (items != null) {
            for (Book item : items) { // 注:此处存在类型不匹配,参数为List<Books>,循环变量应为Books
                item.setOwner(this);
            }
            this.items = Collections.unmodifiableList(items);
        }
    }
    public List<Books> getItems() {
        return items;
    }
}

Kryo 配置代码

public class HelloKryo {
    public static void main (String[] args) throws Exception {
        Kryo kryo = new Kryo();
        kryo.register(TestClass.class);
        kryo.register(Books.class);
        kryo.register(List.class);
        Output output = new Output();
        kryo.writeClassAndObject(output, object); // 注:object变量未定义,需替换为实际TestClass实例
        byte[] result = output.toBytes();     
    } 
}

解决方案

方法1:通过实例获取内部类并注册对应序列化器

由于UnmodifiableMap/UnmodifiableList是包私有内部类,无法直接通过类名引用,可通过创建临时实例获取其Class对象,再注册Kryo的内置序列化器:

Kryo kryo = new Kryo();
kryo.setRegistrationRequired(true);

// 注册业务类和底层集合类
kryo.register(TestClass.class);
kryo.register(Books.class);
kryo.register(ArrayList.class);
kryo.register(HashMap.class);

// 获取不可修改集合的Class对象并注册序列化器
Class<?> unmodifiableListClass = Collections.unmodifiableList(new ArrayList<>()).getClass();
kryo.register(unmodifiableListClass, new CollectionSerializer());

Class<?> unmodifiableMapClass = Collections.unmodifiableMap(new HashMap<>()).getClass();
kryo.register(unmodifiableMapClass, new MapSerializer());

// 后续序列化逻辑
TestClass object = new TestClass(new ArrayList<>());
Output output = new Output();
kryo.writeClassAndObject(output, object);
byte[] result = output.toBytes();

方法2:关闭强制注册(快速解决)

如果业务允许放宽序列化安全性,可关闭Kryo的强制注册要求,让其自动处理未注册的内部类:

Kryo kryo = new Kryo();
// 关闭强制注册,允许Kryo自动处理未注册类
kryo.setRegistrationRequired(false);

kryo.register(TestClass.class);
kryo.register(Books.class);

// 后续序列化逻辑
TestClass object = new TestClass(new ArrayList<>());
Output output = new Output();
kryo.writeClassAndObject(output, object);
byte[] result = output.toBytes();

方法3:自定义序列化器转换集合类型

在序列化时将不可修改集合转为普通集合,反序列化后再恢复为不可修改集合,避免直接处理内部类:

Kryo kryo = new Kryo();
kryo.setRegistrationRequired(true);

// 注册业务类和普通集合类,自定义TestClass序列化逻辑
kryo.register(TestClass.class, new Serializer<TestClass>() {
    @Override
    public void write(Kryo kryo, Output output, TestClass object) {
        // 序列化时将不可修改列表转为ArrayList
        kryo.writeObject(output, new ArrayList<>(object.getItems()));
    }

    @Override
    public TestClass read(Kryo kryo, Input input, Class<TestClass> type) {
        // 反序列化后通过构造方法自动转为不可修改列表
        List<Books> items = kryo.readObject(input, ArrayList.class);
        return new TestClass(items);
    }
});
kryo.register(Books.class);
kryo.register(ArrayList.class);

// 后续序列化逻辑
TestClass object = new TestClass(new ArrayList<>());
Output output = new Output();
kryo.writeClassAndObject(output, object);
byte[] result = output.toBytes();

内容的提问来源于stack exchange,提问作者user25743358

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 01:04:59