Comprendre le serialVersionUID

Comprendre le serialVersionUID

Si vous avez déjà implémenté l'interfaceSerializable, vous devez rencontrer ce message d'avertissement

The serializable class xxx does not declare a static final serialVersionUID field of type long

Alors… qu'est-ce que serialVersionUID?

Le serialVersionUID est utilisé comme contrôle de version dans une classe Serializable. Si vous ne déclarez pas explicitement un serialVersionUID, JVM le fera automatiquement pour vous, en fonction de divers aspects de votre classe Serializable, comme décrit dans lesJava™ Object Serialization Specification.

1. Exemple SerialVersionUID

L'instruction ci-dessus est un peu difficile à comprendre au début (du moins je l'ai fait), commençons par un exemple pour comprendre comment la classe Serializable utilise SerialVersionUID pour implémenter le contrôle de version.

1.1 Address.java

Une classe sérialisable avec un serialVersionUID de 1L.

import java.io.Serializable;

public class Address implements Serializable{

       private static final long serialVersionUID = 1L;

       String street;
       String country;

       public void setStreet(String street){
           this.street = street;
       }

       public void setCountry(String country){
           this.country = country;
       }

       public String getStreet(){
           return this.street;
       }

       public String getCountry(){
           return this.country;
       }

       @Override
       public String toString() {
           return new StringBuffer(" Street : ")
           .append(this.street)
           .append(" Country : ")
           .append(this.country).toString();
       }
}

1.2 WriteObject.java

Une classe simple pour écrire / sérialiser l'objet Address dans un fichier - «c: \ address.ser».

import java.io.FileOutputStream;
import java.io.ObjectOutputStream;

public class WriteObject{

    public static void main (String args[]) {

       Address address = new Address();
       address.setStreet("wall street");
       address.setCountry("united states");

       try{

        FileOutputStream fout = new FileOutputStream("c:\\address.ser");
        ObjectOutputStream oos = new ObjectOutputStream(fout);
        oos.writeObject(address);
        oos.close();
        System.out.println("Done");

       }catch(Exception ex){
           ex.printStackTrace();
       }
    }
}

1.3 ReadObject.java

Une classe simple pour lire / désérialiser l'objet Address à partir du fichier - «c: \ address.ser».

import java.io.FileInputStream;
import java.io.ObjectInputStream;

public class ReadObject{

   public static void main (String args[]) {

       Address address;

       try{

           FileInputStream fin = new FileInputStream("c:\\address.ser");
           ObjectInputStream ois = new ObjectInputStream(fin);
           address = (Address) ois.readObject();
           ois.close();

           System.out.println(address);

       }catch(Exception ex){
           ex.printStackTrace();
       }
   }
}

2. Essai

Laissez faire quelques tests pour démontrer l'utilisation de serialVersionUID.

2.1 Same serialVersionUID

Même serialVersionUID, il n'y a aucun problème pendant le processus de désérialisation

javac Address.java
javac WriteObject.java
javac ReadObject.java
java WriteObject
java ReadObject
Street : wall street Country : united states

2.2 Different serialVersionUID

Dans Address.java,change the serialVersionUID to 2L (c'était 1L), et compilez-le à nouveau.

javac Address.java
java ReadObject
java.io.InvalidClassException: Address; local class incompatible:
stream classdesc serialVersionUID = 1, local class serialVersionUID = 2
        ...
        at ReadObject.main(ReadObject.java:14)

Le «InvalidClassException» augmentera, car vous écrivez une classe de sérialisation avecserialVersionUID “1L” mais essayez de la récupérer avec la classe de sérialisation mise à jour,serialVersionUID “2L”.

Le serialVersionUID doit correspondre pendant le processus de sérialisation et de désérialisation.

When should update your serialVersionUID?
Lorsque votre classe de sérialisation est mise à jour avec des modifications de type Java incompatibles vers une classe sérialisable, vous devez mettre à jour votre serialVersionUID.

Pour plus de détails sur les changements de type Java compatibles et incompatibles vers une classe sérialisable, consultez lesJava Object Serialization Specification.

3. Quel est le problème avec le serialVersionUID par défaut?

Si aucun serialVersionUID n'est déclaré, JVM utilisera son propre algorithme pour générer un SerialVersionUID par défaut, vous pouvez vérifier l'algorithmehere.

The default serialVersionUID computation is highly sensitive to class details and may vary from different JVM implementation et provoquent des InvalidClassExceptions inattendues pendant le processus de désérialisation.

3.1 Client / Server environment

- Le client utilise la JVM de SUN sous Windows.
- Le serveur utilise JRockit sous Linux.

Le client envoie une classe sérialisable avec serialVersionUID généré par défaut (par exemple 123L) au serveur via socket, le serveur peut générer un serialVersionUID différent (par exemple 124L) pendant le processus de désérialisation, et déclenche une InvalidClassExceptions inattendue.

3.2 File / Database environment

- L'application n ° 1 utilise la JVM de SUN sous Windows.
- L'application n ° 2 utilise JRockit sous Linux.

La sérialisation a permis d'enregistrer dans un fichier ou une base de données. L'application n ° 1 stocke une classe sérialisable dans la base de données par défaut serialVersionUID généré (par exemple 123L), tandis que l'application n ° 2 peut générer un serialVersionUID différent (par exemple 124L) pendant le processus de désérialisation, et déclencher une InvalidClassExceptions inattendue.

Vous pouvez vérifier ici lesList of the JVM implementation.

4. Comment générer serialVersionUID

Vous pouvez utiliser JDK «serialver» ou Eclipse IDE pour générer automatiquement serialVersionUID,see detail.

Conclusion

SUN est fortement recommandé aux développeurs de déclarer le serialVersionUID afin d'éviter les différents problèmes JVM répertoriés ci-dessus, mais je vous recommande plutôt de comprendre ce qu'est la sérialisation, comment serialVersionUID implémente le contrôle de version et pourquoi votre classe doit utiliser la sérialisation. Comprendre le concept serialVersionUID est meilleur que les yeux bandés à toute recommandation.