2012-08-09 23 views
5

Estoy tratando de serializar y deserializar objetos de una clase personalizada (por ejemplo, SomeClass, tener un defecto de no-args constructor) a una matriz byte[], utilizando Kryo 2.19 y el serializador predeterminado (FieldSerializer).Java genérico serialización/deserialización usando Kryo

La serialización parece funcionar bien, pero obtengo varias excepciones en la deserialización, dependiendo de la implementación real de SomeClass.

El código es como la siguiente:

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 ejemplo de las excepciones que estoy consiguiendo es:

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) 

Parece que los tipos parametrizados son problemáticos para deserializar. Para probar esta hipótesis, aquí es una aplicación con parámetros de SomeClass y 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); 
} 

Este serializa bien, pero deserialización lanza la siguiente excepción (observar cómo la primera letra de la cadena no se contabiliza en la causa excepción):

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) 

Si la clase anterior se implementa sin parametrización (es decir, la matriz elements declarada como una String[]), deserialización funciona como se espera.

¿Alguna idea?

+1

¿Puedes publicar el código de 'SomeClass' aquí? Recuerdo que en Kryo debes registrar todas las clases que se pueden serializar (por ejemplo, si tu clase usa ArrayList, debería registrarse también). Otra pregunta, ¿funciona para la clase intencionalmente simple? –

+0

Parece que tiene que ver con los genéricos. La clase está parametrizada, es decir, SomeClass con una variable de instancia privada T []. Si esa variable se elimina, funciona. De lo contrario, se lanzan numerosos tipos de excepciones, dependiendo de la variación. – PNS

+1

Esto suena como que debería usar 'SomeClass ' – Dahaka

Respuesta

0

Asegúrese de que utiliza la misma versión de la clase para la serialización y des-serialización. Si serializas utilizando una versión de clase y usas una versión de clase diferente (como por ejemplo después de agregar o eliminar un campo), es probable que se produzca este error. No quiere decir que solo puede ocurrir durante esa situación.

Cuestiones relacionadas