【发布时间】:2012-08-06 11:29:46
【问题描述】:
我正在尝试使用 Kryo 2.19 和默认序列化程序 (FieldSerializer) 将自定义类的对象(例如,SomeClass,具有默认的无参数构造函数)序列化和反序列化为 byte[] 数组.
序列化似乎工作正常,但我在反序列化中遇到各种异常,具体取决于SomeClass 的实际实现。
代码如下所示:
SomeClass object = getObject(); // Create and populate a new object of SomeClass
Kryo kryo = new Kryo();
FieldSerializer<?> serializer = new FieldSerializer<SomeClass>(kryo, SomeClass.class);
kryo.register(SomeClass.class, serializer);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
Output output = new Output(stream);
kryo.writeObject(output, object);
output.close(); // Also calls output.flush()
byte[] buffer = stream.toByteArray(); // Serialization done, get bytes
// Deserialize the serialized object.
object = kryo.readObject(new Input(new ByteArrayInputStream(buffer)), SomeClass.class);
我得到的异常示例是:
Exception in thread "main" java.lang.IncompatibleClassChangeError: Found interface org.objectweb.asm.MethodVisitor, but class was expected
at com.esotericsoftware.reflectasm.ConstructorAccess.insertConstructor(ConstructorAccess.java:89)
at com.esotericsoftware.reflectasm.ConstructorAccess.get(ConstructorAccess.java:70)
at com.esotericsoftware.kryo.Kryo.newInstantiator(Kryo.java:1009)
at com.esotericsoftware.kryo.Kryo.newInstance(Kryo.java:1059)
at com.esotericsoftware.kryo.serializers.FieldSerializer.create(FieldSerializer.java:228)
at com.esotericsoftware.kryo.serializers.FieldSerializer.read(FieldSerializer.java:217)
at com.esotericsoftware.kryo.Kryo.readObject(Kryo.java:629)
似乎参数化类型在反序列化方面存在问题。为了测试这个假设,这里是SomeClass 和getObject() 的参数化实现:
class SomeClass<T extends Serializable>
{
private final T[] elements;
private final int first;
private final int second;
private SomeClass()
{
this.elements = null;
this.first = 0;
this.second = 0;
}
private SomeClass(T[] elements, int first, int second)
{
this.elements = elements;
this.first = first;
this.second = second;
}
}
SomeClass<?> getObject()
{
String[] elements = new String[] {"This is a test", "one"};
return new SomeClass<String>(elements, 1, 2);
}
这样序列化很好,但是反序列化会抛出如下异常(观察异常原因中如何不报字符串首字母):
Exception in thread "main" com.esotericsoftware.kryo.KryoException: Unable to find class: his is a test
Serialization trace:
elements (net.cetas.parserserver.data.report.SourceDataReporter$SomeClass)
at com.esotericsoftware.kryo.util.DefaultClassResolver.readName(DefaultClassResolver.java:132)
at com.esotericsoftware.kryo.util.DefaultClassResolver.readClass(DefaultClassResolver.java:109)
at com.esotericsoftware.kryo.Kryo.readClass(Kryo.java:613)
at com.esotericsoftware.kryo.Kryo.readClassAndObject(Kryo.java:724)
at com.esotericsoftware.kryo.serializers.DefaultArraySerializers$ObjectArraySerializer.read(DefaultArraySerializers.java:338)
at com.esotericsoftware.kryo.serializers.DefaultArraySerializers$ObjectArraySerializer.read(DefaultArraySerializers.java:293)
at com.esotericsoftware.kryo.Kryo.readObjectOrNull(Kryo.java:702)
at com.esotericsoftware.kryo.serializers.FieldSerializer$ObjectField.read(FieldSerializer.java:521)
at com.esotericsoftware.kryo.serializers.FieldSerializer.read(FieldSerializer.java:221)
at com.esotericsoftware.kryo.Kryo.readObject(Kryo.java:629)
如果上述类在没有参数化的情况下实现(即,elements 数组声明为 String[]),则反序列化将按预期工作。
有什么想法吗?
【问题讨论】:
-
你能把“SomeClass”的代码贴在这里吗?我记得在 Kryo 中你应该注册所有可以序列化的类(例如,如果你的类使用 ArrayList,它也应该注册)。另一个问题,它是否适用于故意简单的类?
-
这似乎与泛型有关。该类是参数化的,即带有私有实例变量 T[] 的 SomeClass
。如果该变量被删除,它就可以工作。否则,会抛出多种类型的异常,具体取决于变体。 -
这听起来你应该使用
SomeClass<T extends Serializable> -
这样也行不通。请参阅上述问题的扩展版本。
标签: java serialization deserialization kryo