• Post Reply Bookmark Topic Watch Topic
  • New Topic

How does serialVersionUID works ?  RSS feed

 
Shubham Semwal
Ranch Hand
Posts: 176
3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Sample serialization code -



De-serialization code -



Scenario 1 - Save the serialization object > Add variable extra > de-serialize it.
output - local class incompatiable error(since state is changed since saving).

Scenario 2 - Manually assign serialVersionUID > Save the serialization object > Add variable extra > de-serialize it.
output - successfully de-serialized.

So what's going on with serialVersionUID ? Why does having it only in SerializationDemo class is solving problems with DeSerializationDemo class. Why aren't we checking it for equality somewhere in DeSerializationDemo class ?
 
Tushar Goel
Ranch Hand
Posts: 934
4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The probable reason i thought is in scenario 1 default serial version id is used so when you add the variable version id changed and you got the exception.
But in scenario 2 you have specifically assigned serial version id which doesn't changes after adding any variable. So when you de serialize it then you got
the same version id and your compiler become happy and no error receives.
 
Shubham Semwal
Ranch Hand
Posts: 176
3
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
And how does that works ? Where do the compiler checks it ? how does the deserialization class knows if it's been changed or not ?
 
Campbell Ritchie
Marshal
Posts: 56536
172
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Question too difficult for “beginning”: moving.

What you are doing in the first instance is changing the class definition making the deserialisation impossible. Without an SUID in your class, the JVM (not the compiler) calculates an SUID for the class you are deserialising and for its target class; since those are different you cannot deserialise. For convenience, you can use the serialver tools
serialver SerialisationDemo
SerialisationDemo: private static final long serialVersionUID = -1473898461194980233L;
… and copy the line shown into your .java file and recompile.
I think the SUID is a sort of hash performed on the fields in your class; I have tried adding methods and that doesn't seem to make any difference to the calculated SUID You have several options about SUIDs:-
  • 1: Leave them out. That means the JVM has to calculate the compatibility or otherwise of the .ser file and the .class file.
  • 2: Guess. If you put different SUIDs in different classes, you are telling the JVM that they will be incompatible with each other.
  • 3: Guess. If you write the same value for SUIDs in two different classes you are telling the JVM they are compatible with each other for serialisation irrespective of what their fields are.
  • 4: Let the serialver tool calculate the SUID; if you add fields the different versions will become mutually incompatible.
  • Some classes e.g. java.lang.String have special treatment; String copies the SUID from the Java1.2 version so as to force compatibility between versions. If you add 1L to your class, you are telling the JVM that you want it to treat both versions as the same.

    I suggest you alter your SerialisationDemo class. Give its fields private access and write a toString method and add
    System.out.println(demo);
    You will have to get rid of the getStats method. Then you can see whether you are serialising the extra field.
     
    Campbell Ritchie
    Marshal
    Posts: 56536
    172
    • Likes 1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    When I added the toString method to your class, I got an exception because of SUID differences, so methods are sometimes included in the process of calculating an SUID.
    Please tell us what happened when you followed my suggestions.
     
    Stephan van Hulst
    Saloon Keeper
    Posts: 7973
    143
    • Likes 1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    The compiler does a rather difficult calculation that involves the class' fully qualified name, its constructors and members, and the fully qualified name of it implemented interfaces and extended super class.

    You shouldn't rely on the default serialized form. you should almost always implement these methods:

  • private void writeObject(java.io.ObjectOutputStream out) throws IOException;
  • private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException;
  • private void readObjectNoData() throws ObjectStreamException;


  • Your class should also be final. Making a class Serializable is a huge pain. Don't do it, and if you have to, limit it to simple value types.
     
    Shubham Semwal
    Ranch Hand
    Posts: 176
    3
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    I was interested and perhaps confused about serialVersionUID while working on this problem.

    Campbell Ritchie wrote:3: Guess. If you write the same value for SUIDs in two different classes you are telling the JVM they are compatible with each other for serialisation irrespective of what their fields are.


    The solution seems to be conflicting with the quoted text. As you can see the serialVersionUID is only used during serialization.
    As per rules SUID has to be calculated again during de-serialization. Now since I've manually assigned a value to "1L" to it how can it possibly be equal to the SUID that's being created by DeserializationDemo class under normal circumstances.
     
    Shubham Semwal
    Ranch Hand
    Posts: 176
    3
    • Likes 1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Here are the info that affects the serialization process -

    Changes to a class that can hurt deseriallzatlon :
  • Deleting an instance variable.
  • Changing the declared type of an instance variable.
  • Changing a non-transient instance variable to transient.
  • Moving a class up or down the inheritance hierarchy.
  • Changing a class (anywhere in the object graph) from Serializable to not Serializable.
  • Changing an instance variable to static.


  • Changes to a class that are usually OK :
  • Adding new instance variables to the class.
  • Adding classes to the inheritance tree.
  • Removing classes from the inheritance tree.
  • Changing the access level of an instance variable.
  • Changing an instance variable from transient to non-transient.
  •  
    Santosh Kumar Nayak
    Ranch Hand
    Posts: 193
    Eclipse IDE IntelliJ IDE Java
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Hi All,

    During Serialization static and transient variables are not serialized.

    "serialVersionUID is a static final variable"

    Then how does serialVersionUID used during De-serialization to regenerate the Object

     
    Knute Snortum
    Sheriff
    Posts: 4276
    127
    Chrome Eclipse IDE Java Postgres Database VI Editor
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    It's more like a version number: it helps the deserializing code know if it's the same version it "thinks" it is.  You don't want to deserialize version 2 on a version 1 object.
     
    Campbell Ritchie
    Marshal
    Posts: 56536
    172
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Remember that static fields always have one copy in existence irrespective of how many or how few instances there are of the class. The SUID lives in the Class<T> object and is accessible as long as the class is loaded into memory. Even when there are no instances.
     
    Santosh Kumar Nayak
    Ranch Hand
    Posts: 193
    Eclipse IDE IntelliJ IDE Java
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Static and transient fields are not serialized



    So now with the above code I can conclude as :
    int Id :                                                    available in Deserialized class
    static String name :                                 available in Deserialized class
    transient private int salary:                      Not available in Deserialized class
    private static final SerialVersionUID=1L;   Available in Deserialized class


    Am I correct ? Please let me know your concerns.

     
    Campbell Ritchie
    Marshal
    Posts: 56536
    172
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Santosh Kumar Nayak wrote:. . .
    int Id :                                                    available in Deserialized class
    static String name :                                 available in Deserialized class
    transient private int salary:                      Not available in Deserialized class
    private static final SerialVersionUID=1L;   Available in Deserialized class
    . . .
    You don't serialise or deserialise classes. You serialise objects. The static fields remain available in the class and are accessible from the reconstructed object after serialisation. The id field is included in the serialised file and returns to the reconstructed object. The salary field is omitted from serialisation.
    You are correct about which is accessible and which isn't.
     
    Santosh Kumar Nayak
    Ranch Hand
    Posts: 193
    Eclipse IDE IntelliJ IDE Java
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    GREAT     

    Then why is it said that static fields cannot be Serialized 
     
    Henry Wong
    author
    Sheriff
    Posts: 23295
    125
    C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Santosh Kumar Nayak wrote:
    Then why is it said that static fields cannot be Serialized 


    By default, static fields are not serialized. If you really want them serialized, then you can implement the readObject() and writeObject() methods.

    But... something tells me that is *not* what you are asking...

    Santosh Kumar Nayak wrote:
    static String name :                                 available in Deserialized class


    Yes. Static methods are available from the deserialized instance, but they are available from all the instances. By default, static fields are not serialized, so, during deserialization, it won't be changed. However, that doesn't mean that you don't have access to it when using a deserialized instance.

    Henry
     
    Tony Docherty
    Bartender
    Posts: 3271
    82
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    I think the point that is confusing you is serialVersionUID is a final static variable and by default final static variable are not serialised. However serialVersionUID is a special case and its value (or a default generated value if you haven't specified a serialVersionUID ) is added to the serialised output as part of the class descriptor. When a serialised output is being de-serialised the class descriptor is read in first and the value of serialVersionUID at the point the class was serialised is checked against the classes current value of serialVersionUID and if they are not the same an exception is thrown.
     
    Santosh Kumar Nayak
    Ranch Hand
    Posts: 193
    Eclipse IDE IntelliJ IDE Java
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
       

    Exactly this is the answer I was looking for !!! You made my Day
     
    • Post Reply Bookmark Topic Watch Topic
    • New Topic
    Boost this thread!