sto cercando di serializzare e deserializzare oggetti di una classe personalizzata (ad esempio, SomeClass
, avendo un default no-args costruttore) in una matrice byte[]
, utilizzando Kryo 2.19
e il serializzatore predefinito (FieldSerializer
).Java Generic serializzazione/deserializzazione utilizzando Kryo
La serializzazione sembra funzionare correttamente, ma ottengo varie eccezioni nella deserializzazione, a seconda dell'implementazione effettiva di SomeClass
.
Il codice simile a questa:
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);
Un esempio delle eccezioni che sto ottenendo è:
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)
Sembra che i tipi parametrici sono problematici per deserializzare. Per verificare questa ipotesi, ecco un implementazione parametrizzato di SomeClass
e 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);
}
Questo serializza bene, ma deserializzazione getta la seguente eccezione (osservare come la prima lettera della stringa non è riportata nella causa eccezione):
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)
Se la classe sopra è implementata senza parametrizzazione (cioè, l'array elements
dichiarata come String[]
), deserializzazione funziona come previsto.
Qualche idea?
Puoi pubblicare qui il codice 'SomeClass'? Ricordo che in Kryo dovresti registrare tutte le classi che possono essere serializzate (esempio, se la tua classe usa ArrayList, dovrebbe essere anche registrato). Un'altra domanda, funziona per classe intenzionalmente semplice? –
Sembra avere a che fare con i generici. La classe è parametrizzata, ad esempio SomeClass con una variabile di istanza privata T []. Se quella variabile viene rimossa, funziona. Altrimenti, vengono lanciati numerosi tipi di eccezioni, a seconda della variazione. –
PNS
Sembra che dovresti usare 'SomeClass' –
Dahaka