我有以下自定义异常,我需要使用kryo库进行序列化。
public class CustomException extends Exception {
public CustomException(){}
}
这是我的seralizer
Kryo kryo = new Kryo();
kryo.writeClassAndObject(out, obj);
但序列化会抛出异常。
com.esotericsoftware.kryo.KryoException: Class cannot be created (missing no-arg constructor): java.util.Collections$UnmodifiableRandomAccessList
Serialization trace:
suppressedExceptions (CustomException)
at com.esotericsoftware.kryo.Kryo$DefaultInstantiatorStrategy.newInstantiatorOf( Kryo.java:1272)
at com.esotericsoftware.kryo.Kryo.newInstantiator(Kryo.java:1078)
我已经解决了使用CustomException
JavaSerializer
的问题
kryo.register(CustomException.class, new JavaSerializer());
但是因为JavaSerializer
非常低效(建议在JavaSerializer javadoc中尽可能避免使用)还有其他方法来序列化kryo中的Exception对象吗?
答案 0 :(得分:0)
根据文档,可以通过多种方式解决此问题:
特定类型的序列化程序使用Java代码创建新实例 那种诸如FieldSerializer之类的序列化程序是通用的,必须 处理创建任何类的新实例。默认情况下,如果是一个类 有一个零参数构造函数,然后通过ReflectASM或 反射,否则抛出异常。如果是零参数 构造函数是私有的,尝试通过反射访问它 使用setAccessible。如果这是可以接受的,则为私有零参数 构造函数是允许Kryo创建类实例的好方法 而不影响公共API。
当无法使用ReflectASM或反射时,可以配置Kryo 使用InstantiatorStrategy来处理创建的实例 类。 Objenesis提供了使用JVM的StdInstantiatorStrategy 特定的API,用于创建类的实例而不调用任何类 构造函数。虽然这适用于许多JVM,但零参数是 通常更便携。
kryo.setInstantiatorStrategy(new StdInstantiatorStrategy()); Note that classes must be designed to be created in this way. If a class
期望调用它的构造函数,它可能是未初始化的 通过这种机制创建的状态。
在许多情况下,你可能想要一个策略,Kryo首先在哪里 尝试查找并使用无参数构造函数,如果没有这样做, 它应该尝试使用StdInstantiatorStrategy作为后备,因为 这个根本不会调用任何构造函数。的配置 这种行为可以这样表达:
kryo.setInstantiatorStrategy(new Kryo.DefaultInstantiatorStrategy(new StdInstantiatorStrategy()));但是,默认行为是 需要一个无参数的构造函数。
Objenesis还可以使用Java内置的方法创建新对象 序列化机制。使用它,该类必须实现 java.io.Serializable和a中的第一个零参数构造函数 调用超类。
kryo.setInstantiatorStrategy(new SerializingInstantiatorStrategy()); You may also write your own
InstantiatorStrategy。
要仅自定义特定类型的创建方式,请执行以下操作: 可以设置ObjectInstantiator。这将覆盖ReflectASM, 反射和InstantiatorStrategy。
Registration registration = kryo.register(SomeClass.class); registration.setObjectInstantiator(...); Alternatively, some serializers provide methods that can be overridden to customize object
创建
kryo.register(SomeClass.class, new FieldSerializer(kryo, SomeClass.class) { public Object create (Kryo kryo, Input input, Class type) { return new SomeClass("some constructor arguments", 1234); } });
示例:
/**
* Because the creation/initialization of Kryo instances is rather expensive,
* in a multithreaded scenario you should pool Kryo instances. A very simple solution
* is to bind Kryo instances to Threads using ThreadLocal, like this:
*/
private static final ThreadLocal<Kryo> kryoThreadLocal = new ThreadLocal<Kryo>() {
@Override
protected Kryo initialValue() {
Kryo kryo = new Kryo();
/*
* In many situations, you may want to have a strategy, where Kryo first tries to find and use a no-arg constructor
* and if it fails to do so, it should try to use StdInstantiatorStrategy as a fallback, because this one does
* not invoke any constructor at all. The configuration for this behavior could be expressed like this:
*/
kryo.setInstantiatorStrategy(new Kryo.DefaultInstantiatorStrategy(new StdInstantiatorStrategy()));
return kryo;
}
};