What is serialVersionUID

How many times you have added serialversionuid in to your code. but why? answer is because IDE force to do that. 90% of developers who adding serialversionuid in to there programs they dont know why its really need.

you may familiar with words serialization and deserialization. in simple term java objects are exists only with in the limits of JVM. when JVM exits object value also get destroyed. serialization means you save the objects as bytes in some where. probably in file system. deserialization means you read this bytes as construct the java object again. but how can you make sure class is remain unchanged from serialization to de-serialization?

for example on January 1st in Employee class as follows.

public class Employee {
	private String id;
	private String name;
	private int age;

}

with those you serialized data to file system as empdata.dat on same day

now on January second some one change the class as follows

public class Employee {
	private String id;
	private String name;
	private Date dateOfBirth;
}

if you trying to restore (deserialization)   empdata.dat to Employee class you can see it is not correct. because those are two different formats. Note: technically this will deserialize without error skipping missing field. but business logic wise output may not as expected. 

here is the requirement of serialversionuid. that is used during deserialization to verify that the sender (person who serialize) and receiver (person who deserialize) of a serialized object have loaded classes for that object that are compatible with respect to serialization. in case receiver has loaded a class for the object that has a different serialVersionUID than that used to serialized, then deserialization will ends with 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:

here for easy of understanding we are using save and read to file system. but serialization can happen in runtime it self through the wire. so sender and receiver would be identical worlds than save and read.

even though IDE insisted you to add seriaVersionUID you can still compile program without compiler error. in such case serialization runtime will calculate a default serialVersionUID value for that class. this calculation will based on several factors. therefore we cannot expect same answer for even same class in different JVM and compiler implementations. so it is strongly recommended that all serializable classes explicitly declare serialVersionUID values,  other wise it can ring false alarm even for valid scenarios. To guarantee a consistent serialVersionUID value across different java compiler implementations, a serializable class must declare an explicit serialVersionUID value.

Other point is strongly advised that explicit serialVersionUID declarations use the private modifier where possible, so declarations apply only to the immediately declaring class. there is one case this rule does not apply. that is Array classes.  those cannot declare an explicit serialVersionUID, so those are always have the default computed value, but the requirement for matching serialVersionUID values is waived for array classes.

Lets try this by example.

Create project in your favorite IDE and implement following class. (path name should be change as your needs)

package com.krishantha.sample.java.serialVersion;

import java.io.Serializable;

public class Employee implements Serializable {

	private static final long serialVersionUID = 1L;

	private String name;
	private byte age;
	private String address;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public byte getAge() {
		return age;
	}

	public void setAge(byte age) {
		this.age = age;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	public String whoIsThis() {
		StringBuffer employee = new StringBuffer();
		employee.append(getName()).append(" is ").append(getAge()).append(" years old and lives at ")
				.append(getAddress());
		return employee.toString();
	}

}

then implement bellow class to write serialized object (serialization)

package com.krishantha.sample.java.serialVersion;

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.setName("Ashintha");
		employee.setAge((byte) 30);
		employee.setAddress("Galle");

		FileOutputStream fout = new FileOutputStream("/users/krishantha/employee.obj");
		ObjectOutputStream oos = new ObjectOutputStream(fout);
		oos.writeObject(employee);
		oos.close();
		System.out.println("Process complete");

	}

}

then implement bellow class to read serialized object. (deserialization)

package com.krishantha.sample.java.serialVersion;

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/krishantha/employee.obj");
		ObjectInputStream ois = new ObjectInputStream(fin);
		employee = (Employee) ois.readObject();
		ois.close();

		System.out.println(employee.whoIsThis());

	}

}

now all set. execute the Writer class. it will create file in given path.

Process complete

now execute Reader class it will read the values from object.

Ashintha is 30 years old and lives at Galle

now change serialVersionUID of Employee class and save

private static final long serialVersionUID = 2L;

now again execute Reader class. (make sure not to execute Writer class)

Exception in thread "main" java.io.InvalidClassException: com.krishantha.sample.java.serialVersion.Employee; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 2
	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)

This means Employee class has changed in terms of serialization. you can try to revert to old id and see. it will work.

 

Share this on your world...Share on FacebookShare on Google+Tweet about this on TwitterShare on LinkedInEmail this to someonePrint this page

Leave a Reply