java object stream (serialization and deserialization)

Posted by ebgames56 on Tue, 18 Jun 2019 23:01:15 +0200

1. Serialization and deserialization

Sequencing: refers to the storage of Java object data in heap memory to disk files or to nodes of other networks in some way.
We call this process serialization.
Deserialization: The process of restoring object data from disk files or from network nodes to Java objects.
Why serialization?
In a distributed system, JavaBean objects that need to share data must be serialized. At this time, they need to be transferred over the network. At this time, they must be converted to binary form. The objects stored in HttpSession should be serialized (only the classes that implement the serialized interface can be serialized).

2) Service passivation: If the service finds that some objects have not been active for a long time, then the server will persist these objects in the local disk file (Java object - > binary file). If some objects need to be active, it will search in memory now, find it, use it, find it in the disk file, deserialize the number of objects we get. According to this, it is restored to Java object.

Classes that need to be serialized must implement a serialized interface: java.io.Serializable interface (flag interface [no Abstract method]). The underlying layer will judge that serialization is allowed only if the current object is an instance of Serializable. boolean ret = Java object  instanceof  Serializable;

Most classes in Java have implemented Serializable interfaces.

2. Use object flow to accomplish serialization and deserialization

ObjectOutputStream: Serialization through the writeObject method.
ObjectInputStream: Deserialize by readObject method.
The bytecode object of the object must exist for deserialization.

Let's serialize and deserialize a User object

First, we create a User object, which is the javaBean we usually use.

public class User{
	private int id;
	private String nameString;
	private int age;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getNameString() {
		return nameString;
	}
	public void setNameString(String nameString) {
		this.nameString = nameString;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public User(int id, String nameString, int age) {
		super();
		this.id = id;
		this.nameString = nameString;
		this.age = age;
	}
	@Override
	public String toString() {
		return "User [id=" + id + ", nameString=" + nameString + ", age=" + age
				+ "]";
	}
}
Test:

import java.io.FileOutputStream;
import java.io.ObjectOutputStream;

public class IODemo7 {
	public static void main(String[] args) throws Exception {
		writeObject();
	}
	
	//Serialization of User Objects Using Object Flow
	private static void writeObject() throws Exception {
		ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("user.txt"));
		out.writeObject(new User(1,"Zhang San",18));
		out.close();
	}
}
At this point, the following error will be reported, why? This is because the User class we defined has not implemented the serialization interface yet.


At this point, we should modify the User class to implement the Serializable interface.

import java.io.Serializable;

public class User implements Serializable{
	private int id;
	private String nameString;
	private int age;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getNameString() {
		return nameString;
	}
	public void setNameString(String nameString) {
		this.nameString = nameString;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public User(int id, String nameString, int age) {
		super();
		this.id = id;
		this.nameString = nameString;
		this.age = age;
	}
	@Override
	public String toString() {
		return "User [id=" + id + ", nameString=" + nameString + ", age=" + age
				+ "]";
	}
}

At this point, the User object can be successfully written to the file by running, and then we open something that we can't understand, requiring the input stream of the object stream for deserialization.


Now let's deserialize

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class IODemo7 {
	public static void main(String[] args) throws Exception {
		writeObject();//serialize
		readObject();//Deserialize
	}
	//Serialization of User Objects Using Object Flow
	private static void writeObject() throws Exception {
		ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("user.txt"));
		out.writeObject(new User(1,"Zhang San",18));
		out.close();
	}
	//Deserializing User Objects Using Object Flows
	private static void readObject() throws Exception {
		ObjectInputStream in = new ObjectInputStream(new FileInputStream("user.txt"));
		User user = (User)in.readObject();
		System.out.println(user);//User [id=1, nameString = Zhang San, age=18]
	}
}
Print result: User [id=1, nameString = Zhang San, age=18]

3. Serialized Details Serialized Version

1: What if some data does not need to be serialized, such as passwords?
In theory, static and transient fields cannot be serialized.

Next, we add a password field to our User class, and then add a modifier transient to the front of the field to see the code.

import java.io.Serializable;

public class User implements Serializable{
	private int id;
	transient private int password;//PlustransientModifier
	private String nameString;
	private int age;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public void setPassword(int password) {
		this.password = password;
	}
	public int getPassword() {
		return password;
	}
	public String getNameString() {
		return nameString;
	}
	public void setNameString(String nameString) {
		this.nameString = nameString;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public User(int id, int password, String nameString, int age) {
		super();
		this.id = id;
		this.password = password;
		this.nameString = nameString;
		this.age = age;
	}
	@Override
	public String toString() {
		return "User [id=" + id + ", password=" + password + ", nameString="
				+ nameString + ", age=" + age + "]";
	}
}
At this point the password will not be serialized



2: Serialization version issues:
When deserializing a Java object, the class file of that object must be provided. Now the question is, as the project upgrades, the class file of the system will also be upgraded (adding a field/deleting a field), how to ensure the compatibility of the two class files? Java judges whether the bytecode has changed by serialVersionUID (serialized version number). If the serialVersionUID class is not defined, the question is how to ensure the compatibility of the two class files. Variables, whose values are calculated by JVM based on class-related information, are often computed differently after modification, which results in the failure of object deserialization due to version incompatibility.







At this point, we need to add a serialized ID to our User.


Then we will not report errors after adding or modifying fields, to ensure that the serialized ID is the same.


Summary: In fact, in development, we just need to add a serialized ID to the classes we define. As for serialization and deserialization, the framework will help us to complete!!!

Topics: Java network jvm