使用 Kryo 的通用 Java 序列化/反序列化
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11880035/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Generic Java serialization/deserialization using Kryo
提问by PNS
I am trying to serialize and deserialize objects of a custom class (say, SomeClass
, having a default no-args constructor) to a byte[]
array, using Kryo 2.19
and the default serializer (FieldSerializer
).
我正在尝试使用和默认序列化程序 ( )将自定义类的对象(例如,SomeClass
具有默认的无参数构造函数)序列化和反序列化为byte[]
数组。Kryo 2.19
FieldSerializer
Serialization seems to work OK, but I get various exceptions in deserialization, depending on the actual implementation of SomeClass
.
序列化似乎工作正常,但我在反序列化中遇到各种异常,具体取决于SomeClass
.
The code looks something like this:
代码如下所示:
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);
An example of the exceptions I am getting is:
我得到的例外的一个例子是:
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)
It seems that parameterized types are problematic to deserialize. To test this assumption , here is a parameterized implementation of SomeClass
and getObject()
:
似乎参数化类型在反序列化方面存在问题。为了检验这一假设,这里是一个参数化的实施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);
}
This serializes fine, but deserialization throws the following exception (observe how the first letter of the string is not reported in the exception cause):
这序列化很好,但是反序列化会抛出以下异常(观察异常原因中未报告字符串的第一个字母的方式):
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)
If the above class is implemented without parameterization (i.e., the elements
array declared as a String[]
), deserialization works as expected.
如果上述类是在没有参数化的情况下实现的(即,elements
数组声明为 a String[]
),反序列化按预期工作。
Any ideas?
有任何想法吗?
回答by Pawel
Exception in thread "main" java.lang.IncompatibleClassChangeError: Found interface org.objectweb.asm.MethodVisitor, but class was expected
Please check which version of ASM are you use in your project. MethodVisitor is an interface in ASM up to 3.3. After 4.0 version this is a class.
请检查您在项目中使用的是哪个版本的 ASM。MethodVisitor 是 ASM 3.3 以上的接口。在 4.0 版本之后这是一个类。
Links:
链接:
回答by jothi pillai
Make sure you use the same class version for serialization and de-serialization. If you serialize using one class version and use a different class version(like for e.g after adding or removing a field) then this error is likely to occur. Not to mean it can occur only during that situation.
确保使用相同的类版本进行序列化和反序列化。如果您使用一个类版本进行序列化并使用不同的类版本(例如在添加或删除字段之后),则可能会发生此错误。并不是说它只能在那种情况下发生。