0

I serialse a student class with a private static final long serialVersionUID = 1L and deserialise it.When I change of the instance variable of the Student class and deserialse it,say suppose I changed the name instance variable to fullName and call deserialse without serialising this modifed Student class. I am still able to do the below cast in deserialse method

Student stud=(Student) ois.readObject();

Why doesnt it throw any exception during casting as the incoming deserilased class and the new modifed class are diffrent.Also all the instance variable which remained unmodifed has value restored back after deserialization except the modified ones. However I get the java.io.InvalidClassException when I remove the private static final long serialVersionUID = 1L from my student class and deserialse which is understandable. So When the serialVersionUID match, doesnt it check for any other attributes of the class? What is the concept behind this?

    class Student implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int id;
public String name() {
    return name;
}
public void setname(String name) {
    this.name = name;
}
public int getId() {
    return id;
}
public void setId(int id) {
    this.id = id;
}
}

2 Answers2

2

Not the state of the fields (= the values) are checked, but the class definition (= what fields are available on the class) is checked by using serialVersionUID. SerialVersionUID is an optional field. If you do not define one, the JVM will generate one for you. So if you have a serialized class with value 1L and try to deserialize it with a generated one (e.g. -687991492884005033L) it will result in a InvalidClassException.

From the Java documentation:

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 InvalidClassExceptions during deserialization.

One very relevant answer on the computation of serialVersionUUID is this one; What is a serialVersionUID and why should I use it?

Nico Van Belle
  • 4,911
  • 4
  • 32
  • 49
0

Following are quotes from Discover the secrets of the Java Serialization API, which should answer your questions.

Bold parts are very relevant to your example .

...imagine you create a class, instantiate it, and write it out to an object stream. That flattened object sits in the file system for some time. Meanwhile, you update the class file, perhaps adding a new field. What happens when you try to read in the flattened object?

Well, the bad news is that an exception will be thrown -- specifically, the java.io.InvalidClassException -- because all persistent-capable classes are automatically given a unique identifier. If the identifier of the class does not equal the identifier of the flattened object, the exception will be thrown. However, if you really think about it, why should it be thrown just because I added a field? Couldn't the field just be set to its default value and then written out next time?

Yes, but it takes a little code manipulation. The identifier that is part of all classes is maintained in a field called serialVersionUID. If you wish to control versioning, you simply have to provide the serialVersionUID field manually and ensure it is always the same, no matter what changes you make to the classfile. You can use a utility that comes with the JDK distribution called serialver to see what that code would be by default (it is just the hash code of the object by default).

...

The version control works great as long as the changes are compatible. Compatible changes include adding or removing a method or a field. Incompatible changes include changing an object's hierarchy or removing the implementation of the Serializable interface. A complete list of compatible and incompatible changes is given in the Java Serialization Specification.

Arnaud
  • 17,229
  • 3
  • 31
  • 44