SerialVersionUID in java
SerialVersionUID in Java
Java serialization process associates each Serializable class a version number which is called SerialVersionUID (also known as Stream Unique Identifier). It is used to ensure that during deserialization the same class (that was used during serialize process) is loaded.
Declaration:
private static final long serialVersionUID = 3487495895819393L;
All the serializable classes must declare serialVersionUID but if the class doesn’t declare, then JVM calculates the same and saves it along with the data being serialized. The serialVersionUID should be unique for every Serializable class in your system.
When the class is serializable and it doesn’t define the serialVersionUID, then JVM calculates the same. It uses Secure Hash Algorithm which is a 64-bit hash of the class name, interface class names, methods, and fields. The value is fixed for all compatible classes. If the SUID is not declared for a class, the value defaults to the hash for that class.
How serialVersionUID works?
- When an object is serialized, the serialVersionUID is serialized along with the other contents.
- Later when the same is deserialized, the serialVersionUID from the deserialized object is extracted and compared with the serialVersionUID of the loaded class.
- If the numbers do not match then, InvalidClassException is thrown.
- If the loaded class is not having a serialVersionUID declared, then it is automatically generated by JVM using the same algorithm as before. But there are some concerns when JVM generates the SerialVersionUID stated below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
public class SerializationTest implements Serializable{ private static final long serialVersionUID = -6060750259121824263L; class Employee implements Serializable { private static final long serialVersionUID = 1506041772446026285L; private String name; private int empId; private float salary; public Employee(String name, int empId, float salary) { this.name = name; this.empId = empId; this.salary = salary; } public String getName() { return name; } public int getEmpId() { return empId; } public float getSalary() { return salary; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + empId; result = prime * result + ((name == null) ? 0 : name.hashCode()); result = prime * result + Float.floatToIntBits(salary); return result; } } public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException { Employee emp1 = new SerializationTest().new Employee("John", 1, 20000); ObjectOutput out = new ObjectOutputStream(new FileOutputStream("file.text")); out.writeObject(emp1); out.close(); // Deserailize to object ObjectInput in = new ObjectInputStream(new FileInputStream("file.text")); Employee emp2 = (Employee) in.readObject(); in.close(); System.out.println("instance1 hashcode "+emp1.hashCode()); System.out.println("instance2 hashCode "+ emp2.hashCode());; } } |
Output:
1 2 |
instance1 hashcode 1256426581 instance2 hashCode 1256426581 |
Problem of depending on default SerialVersionUID generated by JVM
- Both sender and receiver should use the same JVM with respect to platform and version also. Otherwise receiver will be unable to deserialize because of different SerialVersionUID.
- Both sender and receiver should use same .class file version. After serialization if there is any change in .class file at receiver side then receiver unable to deserialize.
- To generate SerialVersionUID internally JVM may use complex algorithm which may create performance problem.
When serialVersionUID is different during deserialization
When an object is serialized, the serialVersionUID is serialized along with the other contents. Later when that is deserialized, the serialVersionUID from the deserialized object is extracted and compared with the serialVersionUID of the loaded class. If the numbers do not match then, InvalidClassException is thrown.
Hence its always recommended to declare serialVersionUID ourselves in the class rather than passing the responsibility to JVM.
Happy Learning!!