2012-08-09 15 views
5

Ich versuche Objekte einer benutzerdefinierten Klasse zu serialisieren und deserialisieren (sagen wir, SomeClass, eine Standard mit no-args Konstruktor) zu einem byte[] Array, mit Kryo 2.19 und die Standard-Serializer (FieldSerializer).Generisches Java Serialisierung/Deserialisierung mit Kryo

Serialisierung scheint in Ordnung zu sein, aber ich bekomme verschiedene Ausnahmen in der Deserialisierung, abhängig von der tatsächlichen Implementierung von SomeClass.

Der Code sieht wie folgt aus etwas:

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); 

Ein Beispiel für die Ausnahmen Ich erhalte ist:

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) 

Es scheint, dass parametrisierte Typen problematisch deserialisiert sind. Um diese Annahme zu testen, ist hier eine parametrisierte Implementierung von SomeClass und 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); 
} 

Dieser serialisiert in Ordnung, aber Deserialisierung wirft die folgende Ausnahme (beobachten, wie die ersten Buchstaben der Zeichenkette nicht in der Ausnahme Ursache gemeldet wird):

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) 

Wenn die obige Klasse ohne Parametrierung implementiert ist (dh die elements Array deklariert als String[]), Deserialisierung wie erwartet funktioniert.

Irgendwelche Ideen?

+1

Können Sie den 'SomeClass'-Code hier posten? Ich erinnere mich, dass Sie in Kryo alle Klassen registrieren sollten, die serialisiert werden können (Beispiel: Wenn Ihre Klasse ArrayList verwendet, sollte sie ebenfalls registriert werden). Eine andere Frage, funktioniert es für absichtlich einfache Klasse? –

+0

Es scheint mit Generika zu tun zu haben. Die Klasse ist parametrisiert, d. H. SomeClass mit einer privaten Instanzvariablen T []. Wenn diese Variable entfernt wird, funktioniert es. Andernfalls werden abhängig von der Variation zahlreiche Arten von Ausnahmen ausgelöst. – PNS

+1

Das hört sich so an, als müssten Sie 'SomeClass ' – Dahaka

Antwort

11
Exception in thread "main" java.lang.IncompatibleClassChangeError: Found interface org.objectweb.asm.MethodVisitor, but class was expected 

Bitte überprüfen Sie, welche Version von ASM Sie in Ihrem Projekt verwenden. MethodVisitor ist eine Schnittstelle in ASM bis 3.3. Nach der Version 4.0 ist dies eine Klasse.

Links:

0

Stellen Sie sicher, dass die gleiche Klasse-Version für die Serialisierung und Deserialisierung verwenden. Wenn Sie mit einer Klassenversion serialisieren und eine andere Klassenversion verwenden (wie z. B. nach dem Hinzufügen oder Entfernen eines Felds), tritt dieser Fehler wahrscheinlich auf. Nicht zu meinen, dass es nur in dieser Situation vorkommen kann.