2012-08-09 18 views
5

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?

+1

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? –

+0

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

+1

Sembra che dovresti usare 'SomeClass ' – Dahaka

risposta

0

assicurarsi di utilizzare la stessa versione di classe per la serializzazione e deserializzazione. Se si serializza utilizzando una versione di classe e si utilizza una versione di classe diversa (ad esempio per esempio dopo aver aggiunto o rimosso un campo), è probabile che si verifichi questo errore. Non significa che possa verificarsi solo durante quella situazione.