Ejemplo con Kryo
Veamos un ejemplo muy sencillo de cómo serializar y deserializar clases java usando la librería Kryo
Dependencia de Kryo[editar]
En nuestro proyecto maven/gradle, debemos poner la dependencia de la librería. La última versión en el momento de escribir esto es
compile group: 'com.esotericsoftware', name: 'kryo', version: '5.0.3'
Instanciar y configurar[editar]
Para serializar/deserializar, necesitamos una instancia de Kryo
. Se puede hacer un new
sin más y no necesitamos más configuración. Sin embargo, la configuración por defecto necesita que registremos después las clases que vamos a querer serializar o deserializar con Kryo. No es complejo y es más eficiente luego, pero puede ser algo pesado si tenemos muchas clases distintas. Sería algo como esto
Kryo kryo = new Kryo();
kryo.register(UnaClase.class);
kryo.register(OtraClase.class);
...
Podemos cambiar la configuración para que esto no sea necesario, basta llamar al método setRegistrationRequired(false)
Kryo kryo = new Kryo();
kryo.setRegistrationRequired(false);
Otro detalle a tener en cuenta es que instanciar la clase Kryo
y configurarla es algo pesado, por lo que es conveniente instanciar la clase una sola vez en algún sitio y usar siempre la misma instancia. Pero como las llamadas luego a los métodos de serialización/deserialización no son thread-safe, tenemos que usar synchronized
cada vez que queramos serializar/deserializar si estamos en un entorno multihilo, o bien tener una instancia de Kryo
para cada hilo, o bien usar un pool de instanacias de Kryo
, similar a como se hace con los pool de conexiones de base de datos.
Serializar y Deserializar[editar]
No nos complicamos la vida y vamos con un ejemplo rápido, Intanciamos Kryo
, le decimos que no queremos registrar previamente las clases y serializamos una clase y luego la deserializamos.
La serialización:
Kryo kryo = new Kryo();
kryo.setRegistrationRequired(false);
SomeClass data = new SomeClass();
...
byte[] serialized = new byte[1000];
Output output = new Output(serialized);
kryo.writeClassAndObject(output, data);
SomeClass
es cualquier clase nuestra que queramos convertir a un array de bytes para enviarla por un socket, guardarla en un fichero, etc. La instanciamos y rellenamos en ella los datos o lo que queramos hacer con ella antes de serializarla.
serialized
no es más que un array de bytes donde queremos meter nuestra clase convertida a bytes.
Output
es una clase específica de la librería Kryo. Admite en el constructor varios tipos de almacenes de datos, como el array de bytes, o un OutputStream
de java, etc. En este caso la instanciamos usando el array de bytes serialized
Y listo, sólo queda llamar a kryo.writeClassAndObject<output, data)
. Hay otros métodos posibles. Este nos sirve para que en el array de bytes se escriba, además de los datos en sí, qué clase concreta es. Esto nos facilitará más adelante la deserialización si no sabemos a priori qué clase concreta está almacenada en el array de bytes.
Una vez tenemos el array de bytes relleno, output.position()
nos dice cuantos bytes se han escrito en el array de bytes. Sería desde 0 hasta output.position()
los bytes que debemos enviar por socket, escribir en fichero, etc.
Vamos con la lectura. El mecanismo es igual de simple
Kryo kryo = new Kryo();
kryo.setRegistrationRequired(false);
Input input = new Input(Arrays.copyOfRange(serialized,0, output.position()));
Object o = kryo.readClassAndObject(input);
if (o instanceof SomeClass){
...
}
Esta vez debemos crear una instancia de Input
que es una clase específica de la librería Kryo. Admite varios tipos de fuentes de bytes, como el array de bytes, un InputStream
, etc. Aquí lo creamos cogiendo del array serialized
anterior sólo la parte que se ha escrito con writeClassAndObject
.
Y basta ahora llamar a kryo.readClassAndObject(input)
para reconstruir nuestra clase y tenerla. Al igual que antes, hay más métodos posibles para leer, pero depende de si nuestra clase está o no registrada, qué método hayamos usado para escribir, etc. La clase que obtenemos es de tipo Object
, así que ahora no nos queda más remedio que verificar de qué tipo es antes de usarla.