Che cos’è un serialVersionUID e perché dovrei usarlo?

Eclipse emette avvisi quando manca un serialVersionUID .

La class serializzabile Foo non dichiara un campo seriale serialVersionUID finale di tipo lungo

Cos’è serialVersionUID e perché è importante? Si prega di mostrare un esempio in cui manca serialVersionUID causerà un problema.

I documenti per java.io.Serializable sono probabilmente una spiegazione valida per te:

Il runtime di serializzazione associa a ciascuna class serializzabile un numero di versione, chiamato serialVersionUID, utilizzato durante la deserializzazione per verificare che il mittente e il destinatario di un object serializzato abbiano caricato classi per quell’object che sono compatibili con la serializzazione. Se il destinatario ha caricato una class per l’object che ha un serialVersionUID diverso da quello della class del mittente corrispondente, la deserializzazione produrrà una InvalidClassException . Una class serializzabile può dichiarare il proprio serialVersionUID esplicitamente dichiarando un campo denominato ” serialVersionUID ” che deve essere statico, definitivo e di tipo long :

 ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L; 

Se una class serializzabile non dichiara esplicitamente un serialVersionUID, il runtime di serializzazione calcolerà un valore serialVersionUID predefinito per quella class in base a vari aspetti della class, come descritto nella specifica di serializzazione dell’object Java (TM). Tuttavia, si consiglia vivamente che tutte le classi serializzabili dichiarino esplicitamente i valori serialVersionUID, poiché il calcolo serialVersionUID predefinito è estremamente sensibile ai dettagli della class che possono variare a seconda delle implementazioni del compilatore e può pertanto comportare imprevisti InvalidClassExceptions durante la deserializzazione. Pertanto, per garantire un valore serialVersionUID coerente tra diverse implementazioni del compilatore java, una class serializzabile deve dichiarare un valore serialVersionUID esplicito. È inoltre vivamente consigliato che le dichiarazioni esplicite serialVersionUID utilizzino il modificatore privato laddove ansible, poiché tali dichiarazioni si applicano solo alla class immediatamente dichiarante – i campi serialVersionUID non sono utili come membri ereditati.

Se stai serializzando solo perché devi serializzare per il bene dell’implementazione (a chi importa se serializzi per un HTTPSession, per esempio … se è memorizzato o meno, probabilmente non ti interessa la serializzazione di un object modulo) , quindi puoi ignorarlo.

Se si utilizza effettivamente la serializzazione, è importante solo se si pianifica di archiviare e recuperare oggetti utilizzando direttamente la serializzazione. SerialVersionUID rappresenta la versione della tua class e dovresti incrementarla se la versione corrente della tua class non è retrocompatibile con la sua versione precedente.

La maggior parte delle volte, probabilmente non utilizzerai la serializzazione direttamente. In questo caso, genera un UID serializzabile predefinito facendo clic sull’opzione di correzione rapida e non preoccuparti.

Non posso perdere questa occasione per colbind il libro di Josh Bloch, Effective Java (2nd Edition). Il capitolo 11 è una risorsa indispensabile sulla serializzazione Java.

Per Josh, l’UID generato automaticamente viene generato sulla base di un nome di class, interfacce implementate e tutti i membri pubblici e protetti. Modificando uno di questi in qualsiasi modo cambierà serialVersionUID . Quindi non è necessario pasticciarli solo se si è certi che non verrà serializzata più di una versione della class (tra processi o recuperati dallo storage in un momento successivo).

Se li ignori per ora, e scopri in seguito che hai bisogno di cambiare la class in qualche modo, ma mantieni la compatibilità con la vecchia versione della class, puoi usare lo strumento JDK serialver per generare serialVersionUID sulla vecchia class ed impostare esplicitamente quello sulla nuova class. (A seconda delle modifiche, potrebbe essere necessario implementare anche la serializzazione personalizzata aggiungendo i metodi writeObject e readObject : vedere javadoc Serializable o capitolo 11 precedente).

Puoi dire a Eclipse di ignorare questi avvisi di serialVersionUID:

Finestra> Preferenze> Java> Compilatore> Errori / Avvisi> Potenziali problemi di programmazione

Nel caso in cui non lo sapessi, ci sono molti altri avvisi che puoi abilitare in questa sezione (o anche alcuni di quelli segnalati come errori), molti sono molto utili:

  • Potenziali problemi di programmazione: Possibile assegnazione booleana accidentale
  • Potenziali problemi di programmazione: accesso al puntatore nullo
  • Codice non necessario: la variabile locale non viene mai letta
  • Codice non necessario: controllo null ridondante
  • Codice non necessario: cast non necessario o ‘instanceof’

e molti altri.

serialVersionUID facilita il controllo delle versioni dei dati serializzati. Il suo valore è memorizzato con i dati durante la serializzazione. Quando si deserializza, viene verificata la stessa versione per vedere come i dati serializzati corrispondono al codice corrente.

Se si desidera eseguire la versione dei dati, di solito si inizia con un serialVersionUID di 0 e si serialVersionUID bump con ogni modifica strutturale alla class che altera i dati serializzati (aggiunta o rimozione di campi non transitori).

Il meccanismo di de-serializzazione in.defaultReadObject() ( in.defaultReadObject() ) rifiuterà di in.defaultReadObject() da vecchie versioni dei dati. Ma se lo desideri, puoi definire la tua funzione readObject () che può leggere i vecchi dati. Questo codice personalizzato può quindi controllare serialVersionUID per sapere in quale versione si trovano i dati e decidere come serialVersionUID . Questa tecnica di versioning è utile se memorizzi dati serializzati che sopravvivono a diverse versioni del tuo codice.

Ma la memorizzazione di dati serializzati per un così lungo periodo di tempo non è molto comune. È molto più comune utilizzare il meccanismo di serializzazione per scrivere temporaneamente dati ad esempio su una cache o inviarli tramite la rete a un altro programma con la stessa versione delle parti rilevanti della base di codice.

In questo caso non sei interessato a mantenere la retrocompatibilità. Ti preoccupi solo di assicurarti che le basi di codice che comunicano abbiano effettivamente le stesse versioni delle classi pertinenti. Per facilitare tale controllo, è necessario mantenere serialVersionUID come prima e non dimenticare di aggiornarlo quando si apportano modifiche alle classi.

Se ti dimentichi di aggiornare il campo, potresti finire con due diverse versioni di una class con struttura diversa ma con lo stesso serialVersionUID . Se ciò accade, il meccanismo predefinito ( in.defaultReadObject() ) non rileverà alcuna differenza e tenterà di in.defaultReadObject() dati incompatibili. Ora si potrebbe finire con un errore di runtime criptico o un errore silenzioso (campi nulli). Questi tipi di errori potrebbero essere difficili da trovare.

Quindi, per aiutare questo usecase, la piattaforma Java offre la possibilità di non impostare manualmente serialVersionUID . Invece, un hash della struttura di class verrà generato in fase di compilazione e utilizzato come id. Questo meccanismo farà in modo di non avere mai strutture di classi diverse con lo stesso id e quindi non otterrete questi errori di serializzazione di runtime hard-to-trace citati sopra.

Ma c’è un retro della strategia di identificazione generata automaticamente. Vale a dire che gli ID generati per la stessa class potrebbero differire tra i compilatori (come menzionato sopra da Jon Skeet). Quindi se comunichi i dati serializzati tra il codice compilato con diversi compilatori, si consiglia comunque di mantenere gli id ​​manualmente comunque.

E se sei retrocompatibile con i tuoi dati come nel caso di primo utilizzo menzionato, probabilmente vorresti anche tu mantenere l’id da solo. Questo al fine di ottenere id leggibili e avere un maggiore controllo su quando e come cambiano.

Che cos’è un serialVersionUID e perché dovrei usarlo?

SerialVersionUID è un identificatore univoco per ogni class, JVM utilizza per confrontare le versioni della class assicurando che sia stata utilizzata la stessa class durante il caricamento della serializzazione durante la deserializzazione.

Specificarne uno dà più controllo, anche se JVM ne genera uno se non lo si specifica. Il valore generato può variare tra diversi compilatori. Inoltre, a volte vuoi solo per qualche motivo proibire la deserializzazione di vecchi oggetti serializzati [ backward incompatibility ], e in questo caso devi solo cambiare serialVersionUID.

I javadoc per Serializable dicono :

il calcolo predefinito di serialVersionUID è estremamente sensibile ai dettagli della class che possono variare a seconda delle implementazioni del compilatore e può pertanto provocare InvalidClassException s inattesi durante la deserializzazione.

Pertanto, è necessario dichiarare serialVersionUID perché ci dà più controllo .

Questo articolo ha alcuni punti positivi sull’argomento.

La domanda originale ha chiesto “perché è importante” e “esempio” in cui questo Serial Version ID sarebbe utile. Bene, ho trovato uno.

Supponi di creare una class Car , di istanziarla e di scriverla su un stream di oggetti. L’object appiattito si trova nel file system per un po ‘di tempo. Nel frattempo, se la class Car viene modificata aggiungendo un nuovo campo. In seguito, quando si tenta di leggere (cioè deserializzare) l’object Car appiattito, si ottiene java.io.InvalidClassException – poiché a tutte le classi serializzabili viene automaticamente assegnato un identificatore univoco. Questa eccezione viene generata quando l’identificatore della class non è uguale all’identificatore dell’object appiattito. Se ci pensi veramente, l’eccezione viene generata a causa dell’aggiunta del nuovo campo. È ansible evitare che questa eccezione venga generata controllando il controllo delle versioni dichiarando un serialVersionUID esplicito. C’è anche un piccolo vantaggio prestazionale nel dichiarare esplicitamente il tuo serialVersionUID (perché non deve essere calcolato). Pertanto, è consigliabile aggiungere il proprio serialVersionUID alle classi Serializable non appena le crei come mostrato di seguito:

 public class Car { static final long serialVersionUID = 1L; //assign a long value } 

Se ricevi questo avvertimento in una class che non hai mai pensato di serializzare, e che non hai dichiarato di implements Serializable , è spesso perché hai ereditato da una superclass, che implementa Serializable. Spesso quindi sarebbe meglio debind a tale object invece di usare l’ereditarietà.

Quindi, invece di

 public class MyExample extends ArrayList { public MyExample() { super(); } ... } 

fare

 public class MyExample { private List myList; public MyExample() { this.myList = new ArrayList(); } ... } 

e nei metodi rilevanti chiama myList.foo() invece di this.foo() (o super.foo() ). (Questo non si adatta in tutti i casi, ma ancora abbastanza spesso.)

Vedo spesso persone che estendono JFrame o simili, quando hanno solo bisogno di debind a questo. (Questo aiuta anche a completare automaticamente in un IDE, poiché JFrame ha centinaia di metodi, che non ti servono quando vuoi chiamare quelli personalizzati nella tua class.)

Un caso in cui l’avvertenza (o serialVersionUID) è inevitabile è quando si estrae da AbstractAction, normalmente in una class anonima, solo aggiungendo il metodo actionPerformsd. Penso che non ci dovrebbe essere un avvertimento in questo caso (dato che normalmente non è ansible serializzare e deserializzare tali classi anonime in tutte le versioni della tua class), ma non sono sicuro di come il compilatore possa riconoscerlo.

Se non avrai mai bisogno di serializzare i tuoi oggetti su array di byte e inviarli / memorizzarli, non dovrai preoccuparti di questo. Se lo fai, allora devi considerare il tuo serialVersionUID poiché il deserializzatore dell’object lo abbinerà alla versione dell’object che ha il suo classloader. Maggiori informazioni su questo argomento nella specifica del linguaggio Java.

Per capire il significato del campo serialVersionUID, si dovrebbe capire come funziona la serializzazione / deserializzazione.

Quando un object di class Serializable è serializzato, Java Runtime associa un numero di versione seriale (chiamato come serialVersionUID) con questo object serializzato. Al momento della deserializzazione di questo object serializzato, Java Runtime corrisponde a serialVersionUID dell’object serializzato con serialVersionUID della class. Se entrambi sono uguali, solo procede con l’ulteriore processo di deserializzazione, altrimenti lancia InvalidClassException.

Quindi concludiamo che per rendere efficace il processo di serializzazione / deserializzazione il serialVersionUID dell’object serializzato deve essere equivalente al serialVersionUID della class. Nel caso in cui il programmatore specifichi esplicitamente il valore serialVersionUID nel programma, lo stesso valore sarà associato all’object serializzato e alla class, indipendentemente dalla piattaforma di serializzazione e deserializzazione (per esempio la serializzazione potrebbe essere eseguita su piattaforms come Windows usando sole o MS JVM e Deserialization potrebbero trovarsi su diverse piattaforms Linux usando Zing JVM).

Ma nel caso in cui serialVersionUID non venga specificato dal programmatore, mentre esegue Serialization \ DeSerialization di qualsiasi object, Java runtime utilizza il proprio algoritmo per calcolarlo. Questo algoritmo di calcolo serialVersionUID varia da un JRE a un altro. È anche ansible che l’ambiente in cui l’object è serializzato utilizzi un JRE (es: SUN JVM) e l’ambiente in cui avviene la deserializzazione si sta utilizzando Linux Jvm (zing). In questi casi, serialVersionUID associato all’object serializzato sarà diverso rispetto a serialVersionUID della class calcasting in ambiente di deserializzazione. A sua volta la deserializzazione non avrà successo. Per evitare tali situazioni / problemi, il programmatore deve sempre specificare serialVersionUID della class Serializable.

Non preoccupatevi, il calcolo predefinito è veramente buono e sufficiente per il 99,9999% dei casi. E se ti imbatti in problemi, puoi – come già affermato – introdurre gli UID come il bisogno di arrise (che è altamente improbabile)

Come per un esempio in cui il serialVersionUID mancante potrebbe causare un problema:

Sto lavorando a questa applicazione Java EE che è composta da un modulo Web che utilizza un modulo EJB . Il modulo web chiama il modulo EJB remoto e passa un POJO che implementa Serializable come argomento.

POJO's class di questo POJO's stata impacchettata all’interno del jar EJB e all’interno del proprio jar nel WEB-INF / lib del modulo web. In realtà sono della stessa class, ma quando impacchetta il modulo EJB, spacchetto questo jar di POJO per comprarlo insieme al modulo EJB.

La chiamata al EJB stava fallendo con l’Eccezione di seguito perché non avevo dichiarato il suo serialVersionUID :

 Caused by: java.io.IOException: Mismatched serialization UIDs : Source (Rep. IDRMI:com.hordine.pedra.softbudget.domain.Budget:5CF7CE11E6810A36:04A3FEBED5DA4588) = 04A3FEBED5DA4588 whereas Target (Rep. ID RMI:com.hordine.pedra.softbudget.domain.Budget:7AF5ED7A7CFDFF31:6227F23FA74A9A52) = 6227F23FA74A9A52 

Generalmente uso serialVersionUID in un contesto: quando so che lascerà il contesto della Java VM.

Lo saprei quando uso ObjectInputStream e ObjectOutputStream per la mia applicazione o se so che una libreria / framework che uso lo userà. Il serialVersionID garantisce che diverse VM Java di versioni o venditori diversi interagiscano correttamente o se vengono archiviate e recuperate al di fuori della VM, ad esempio HttpSession i dati della sessione possono rimanere anche durante il riavvio e l’aggiornamento del server delle applicazioni.

Io uso per tutti gli altri casi

 @SuppressWarnings("serial") 

poiché la maggior parte delle volte il serialVersionUID predefinito è sufficiente. Ciò include Exception , HttpServlet .

I dati del campo rappresentano alcune informazioni memorizzate nella class. La class implementa l’interfaccia Serializable , quindi eclipse viene automaticamente offerto per dichiarare il campo serialVersionUID . Iniziamo con il valore 1 impostato lì.

Se non vuoi che questo avviso venga, usa questo:

 @SuppressWarnings("serial") 

Per prima cosa ho bisogno di spiegare la serializzazione.
La serializzazione consente di convertire l’object nello stream, per inviare quell’object alla rete OPPURE Salva nel file OPPURE salvare nel DB per l’utilizzo della lettera.

Ci sono alcune regole per la serializzazione .

  • Un object è serializzabile solo se la sua class o la sua superclass implementa l’interfaccia Serializable

  • Un object è serializzabile (implementa di per sé l’interfaccia Serializable) anche se la sua superclass non lo è. Tuttavia, la prima superclass nella gerarchia della class serializzabile, che non implementa un’interfaccia serializzabile, DEVE avere un costruttore no-arg. Se questo viene violato, readObject () produrrà una java.io.InvalidClassException in runtime

  • Tutti i tipi primitivi sono serializzabili.

  • I campi transitori (con modificatore transitorio) NON sono serializzati, (cioè non salvati o ripristinati). Una class che implementa Serializable deve contrassegnare i campi transitori di classi che non supportano la serializzazione (ad esempio, un stream di file).

  • I campi statici (con modificatore statico) non sono serializzati.

Quando l’object viene serializzato, JAVA Runtime associa il numero di versione seriale chiamato serialVersionID.

Dove è necessario serialVersionID: durante la deserializzazione per verificare che mittente e destinatario siano compatibili rispetto alla serializzazione. Se il ricevitore ha caricato la class con un serialVersionID diverso, la deserializzazione terminerà con InvalidClassCastException .
Una class serializzabile può dichiarare esplicitamente il proprio serialVersionUID dichiarando un campo denominato “serialVersionUID” che deve essere statico, finale e di tipo long :.

Proviamo questo con un esempio.

 import java.io.Serializable; public class Employee implements Serializable { private static final long serialVersionUID = 1L; private String empname; private byte empage; public String getEmpName() { return name; } public void setEmpName(String empname) { this.empname = empname; } public byte getEmpAge() { return empage; } public void setEmpAge(byte empage) { this.empage = empage; } public String whoIsThis() { StringBuffer employee = new StringBuffer(); employee.append(getEmpName()).append(" is ).append(getEmpAge()).append(" years old ")); return employee.toString(); } } 

Crea object serializza

 import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; public class Writer { public static void main(String[] args) throws IOException { Employee employee = new Employee(); employee.setEmpName("Jagdish"); employee.setEmpAge((byte) 30); FileOutputStream fout = new FileOutputStream("/users/Jagdish.vala/employee.obj"); ObjectOutputStream oos = new ObjectOutputStream(fout); oos.writeObject(employee); oos.close(); System.out.println("Process complete"); } } 

Deserializ l’object

 import java.io.FileInputStream; import java.io.IOException; import java.io.ObjectInputStream; public class Reader { public static void main(String[] args) throws ClassNotFoundException, IOException { Employee employee = new Employee(); FileInputStream fin = new FileInputStream("/users/Jagdish.vala/employee.obj"); ObjectInputStream ois = new ObjectInputStream(fin); employee = (Employee) ois.readObject(); ois.close(); System.out.println(employee.whoIsThis()); } } 

NOTE: Now change the serialVersionUID of the Employee class and save:

 private static final long serialVersionUID = **4L**; 

And execute the Reader class. Not to execute the Writer class and you will get the exception.

 Exception in thread "main" java.io.InvalidClassException: com.jagdish.vala.java.serialVersion.Employee; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 4 at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:616) at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1623) at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1518) at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1774) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371) at com.krishantha.sample.java.serialVersion.Reader.main(Reader.java:14) 

It would be nice if CheckStyle could verify that the serialVersionUID on a class that implements Serializable has a good value, ie that it matches what the serial version id generator would produce. If you have a project with lots of serializable DTOs, for example, remembering to delete the existing serialVersionUID and regenerate it is a pain, and currently the only way (that I know of) to verify this is to regenerate for each class and compare to the old one. This is very very painful.

SerialVersionUID is used for version control of object. you can specify serialVersionUID in your class file also. Consequence of not specifying serialVersionUID is that when you add or modify any field in class then already serialized class will not be able to recover because serialVersionUID generated for new class and for old serialized object will be different. Java serialization process relies on correct serialVersionUID for recovering state of serialized object and throws java.io.InvalidClassException in case of serialVersionUID mismatch

Read more: http://javarevisited.blogspot.com/2011/04/top-10-java-serialization-interview.html#ixzz3VQxnpOPZ

Why use SerialVersionUID inside Serializable class in Java?

During serialization , Java runtime creates a version number for a class, so that it can de-serialize it later. This version number is known as SerialVersionUID in Java.

SerialVersionUID is used to version serialized data. You can only de-serialize a class if it’s SerialVersionUID matches with the serialized instance. When we don’t declare SerialVersionUID in our class, Java runtime generates it for us but its not recommended. It’s recommended to declare SerialVersionUID as private static final long variable to avoid default mechanism.

When you declare a class as Serializable by implementing marker interface java.io.Serializable , Java runtime persist instance of that class into disk by using default Serialization mechanism, provided you have not customized the process using Externalizable interface.

see also Why use SerialVersionUID inside Serializable class in Java

Code : javassist.SerialVersionUID

If you want to amend a huge number of classs which had no serialVersionUID set in the first place while maintain the compatibility with the old classs, tools like IntelliJ Idea, Eclipse fall short as they generate random numbers and does not work on a bunch of files in one go. I come up the following bash script(I’m sorry for Windows users, consider buy a Mac or convert to Linux) to make amending serialVersionUID issue with ease:

 base_dir=$(pwd) src_dir=$base_dir/src/main/java ic_api_cp=$base_dir/target/classs while read f do clazz=${f//\//.} clazz=${clazz/%.java/} seruidstr=$(serialver -classpath $ic_api_cp $clazz | cut -d ':' -f 2 | sed -e 's/^\s\+//') perl -ni.bak -e "print $_; printf qq{%s\n}, q{ private $seruidstr} if /public class/" $src_dir/$f done 

you save the this script, say add_serialVersionUID.sh to you ~/bin. Then you run it in the root directory of your Maven or Gradle project like:

 add_serialVersionUID.sh < myJavaToAmend.lst 

This .lst includes the list of java files to add the serialVersionUID in the following format:

 com/abc/ic/api/model/domain/item/BizOrderTransDO.java com/abc/ic/api/model/domain/item/CardPassFeature.java com/abc/ic/api/model/domain/item/CategoryFeature.java com/abc/ic/api/model/domain/item/GoodsFeature.java com/abc/ic/api/model/domain/item/ItemFeature.java com/abc/ic/api/model/domain/item/ItemPicUrls.java com/abc/ic/api/model/domain/item/ItemSkuDO.java com/abc/ic/api/model/domain/serve/ServeCategoryFeature.java com/abc/ic/api/model/domain/serve/ServeFeature.java com/abc/ic/api/model/param/depot/DepotItemDTO.java com/abc/ic/api/model/param/depot/DepotItemQueryDTO.java com/abc/ic/api/model/param/depot/InDepotDTO.java com/abc/ic/api/model/param/depot/OutDepotDTO.java 

This script uses the JDK serialVer tool under hood. So make sure your $JAVA_HOME/bin is in the PATH.

This question is very well documented in Effective Java by Joshua Bloch. A very good book and a must read. I will outline some of the reasons below :

The serialization runtime comes up with a number called Serial version for each serializable class. This number is called serialVersionUID. Now there is some Math behind this number and it comes out based on the fields/methods that are defined in the class. For the same class the same version is generated every time. This number is used during deserialization to verify that the sender and receiver of a serialized object have loaded classs 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.

If the class is serializable you can also declare your own serialVersionUID explicitly by declaring a field named “serialVersionUID” that must be static, final, and of type long. Most IDE’s like Eclipse help you generate that long string.

Each time an object is serialized the object is stamped with a version ID number for the object’s class.This ID is called serialVersionUID and it is computed based on information about the class structure. Suppose you made an Employee class and it has version id #333 (assigned by JVM),Now when you will serialize the object of that class (Suppose Employee object), JVM will assign UID to it as #333.

Consider a situation – in the future you need to edit or change your class and in that case when you modify it, JVM will assign it a new UID (Suppose #444). Now when you try to deserialize the employee object, JVM will compare serialized object’s (Employee object) version ID(#333) with that of the class ie #444(Since it was changed). On comparison JVM will find both version UID are different and hence Deserialization will fail. Hence if serialVersionID for each class is defined by programmer itself. It will be same even if the class is evolved in future and hence JVM will always find that class is compatible with serialized object even though the class is changed. For more Info you can refer chapter 14 of HEAD FIRST JAVA.