jueves, 28 de agosto de 2008

java: serialVersionUID

Serializacion y el serialVersionUID

El siguiente parrafo corresponde al Javadoc para la interface Serializable:

The serialization runtime associates with each serializable class a version number, called a serialVersionUID, which is used during deserialization to verify that the sender and receiver of a serialized object have loaded classes for that object that are compatible with respect to serialization. If the receiver has loaded a class for the object that has a different serialVersionUID than that of the corresponding sender's class, then deserialization will result in an InvalidClassException. A serializable class can declare its own serialVersionUID explicitly by declaring a field named "serialVersionUID" that must be static, final, and of type long:

 ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;
If a serializable class does not explicitly declare a serialVersionUID, then the serialization runtime will calculate a default serialVersionUID value for that class based on various aspects of the class, as described in the Java(TM) Object Serialization Specification. However, it is strongly recommended that all serializable classes explicitly declare serialVersionUID values, since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations, and can thus result in unexpected InvalidClassException's during deserialization. Therefore, to guarantee a consistent serialVersionUID value across different java compiler implementations, a serializable class must declare an explicit serialVersionUID value. It is also strongly advised that explicit serialVersionUID declarations use the private modifier where possible, since such declarations apply only to the immediately declaring class--serialVersionUID fields are not useful as inherited members.

Uso del serialVersionUID


El uso mas importante que se le da a este dato de una clase es cuando se serializan/deserializan clases en un sistema distrubuido, donde el intercambio de objetos entre componentes remotos del sistema es algo comun. Existen varios motivos por los cuales generar el sUID estaticamente es necesario, aunque depende del caso.

Generacion dinamica del serialVersionUID

Lo esperable es que el contenedor de la aplicacion genere este sUID en caso de no encontrarlo en la clase a serializar. La generacion de este identificador afecta la performance del sistema ya que la clase debe ser inspeccionada.
Otro problema asociado a la generacion dinamica del sUID es que si la clase serializada fue compilada empleando un compilador o version de Java diferente a la usada para la clase que se encuentra en entorno remoto, entonces ocurria un error de compatibilidad. Esto se debe a que el bytecode generado por compiladores diferentes o version de Java diferentes es distinto.

Generacion estatica del serialVersionUID

La generacion estatica del sUID consiste en agregar en el codigo de la clase a serializar un dato static y long identificado con el nombre serialVersionUID. El valor asociado a este dato debe ser consistente con la composicion de la clase. Actualmente, entornos de desarrollo como Eclipse incluyen la funcionalidad necesaria para generar dicho valor.

Cambios en clases serializables

Cambios en la composicion de una clase que implementa la interfaz Serializable pueden o no generar una excepcion del tipo java.io.InvalidClassException.
Los cambios que no generan incompatibilidad para una clase durante el proceso de serializacion/deserializacion son:
  • Agregar un dato (miembro/atributo)
  • Cambiar el modificador de un dato de static a no-static
  • Cambiar el modificador de un dato de transient a no-transient
Los cambios que generar errores de compatibilidad son:
  • Eliminar un dato (miembro/atributo)
  • Cambiar el tipo de un dato primitivo
  • Convertir un dato a static
  • Convertir un dato a transient
  • Modificar la gerarquia de clases
Suprimir alertas

Una forma de evitar el warning por parte del compilador o en un entorno de desarrollo como Eclipse, es utilizar la siguiente anotacion a nivel de clase:
@SuppressWarnings("serial")
de la siguiente manera:
@SuppressWarnings("serial")
public class SomeClass {
...
}
Vinculos:

No hay comentarios.: