通用Java序列化使用KRYO
问题描述:
我试图序列化和反序列化的自定义类的对象(比如,SomeClass
,有一个默认的无参数的构造函数)到byte[]
阵列,使用Kryo 2.19
和默认的序列(FieldSerializer
)/反序列化。通用Java序列化使用KRYO
序列化似乎工作正常,但我得到各种反序列化异常,具体取决于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[]
),反序列化按预期工作。
任何想法?
答
Exception in thread "main" java.lang.IncompatibleClassChangeError: Found interface org.objectweb.asm.MethodVisitor, but class was expected
请检查您的项目中使用了哪个版本的ASM。 MethodVisitor是ASM中3.3以下的接口。 4.0版后,这是一个类。
链接:
答
确保您使用相同的类版本序列化和反序列化。如果您使用一个类版本进行序列化并使用不同的类版本(例如添加或删除字段后),则可能会发生此错误。并不意味着它只能在这种情况下发生。
你可以在这里发布'SomeClass'的代码吗?我记得在Kryo中,你应该注册所有可以序列化的类(例如,如果你的类使用ArrayList,它也应该被注册)。另一个问题,它是否适用于故意简单的课程? – 2012-08-09 09:54:49
这似乎与仿制药有关。该类是参数化的,即具有私有实例变量T []的SomeClass。如果该变量被删除,它将起作用。否则,根据变化情况,会抛出许多类型的异常。 –
PNS
2012-08-09 10:22:31
这听起来像你应该使用'SomeClass' –
Dahaka
2012-08-09 10:31:51