Serialization and deserialization technology and local serialization technology of IO stream

Keywords: Java

1, Overview

  • serialize
    • The objects in the program are stored directly in the form of files according to the sequence of objects in memory
  • Deserialization
    • Reread the object data from the file into the program
      • Is to read out the previously serialized object from the file and change it into an object again
  • In 2018, java officials found that at least 1 / 3 of the bug s in the program were caused by the use of serialization and deserialization technology. If this serialization security problem cannot be replaced by more appropriate technology, serialization technology will not be eliminated in the short term, otherwise the whole java ecology will be affected

2, Implement serialization

1. Serializable interface implements serialization

  • To implement serialized classes, you need to implement the Serializable interface and use the object output stream ObjectOutputStream
  • This is a tag interface
    • In the underlying source code, ObjectOutputStream will judge whether the written object is a string, or use instanceof to judge whether it is Serializable or its implementation class. If these conditions are not met, an exception will be thrown
  • Using ObjectOutputStream requires an OutputStream object to be passed in
  • If a class that implements the Serializable interface wants to be serialized, all properties must also implement the Serializable interface, otherwise it cannot be serialized

2. Four ways to realize partial attribute serialization

  • Modifying attributes with transient
    • The premise is that this class implements the Serializable interface
    • Attributes modified by transient are not serialized
  • Using the static modifier
    • The premise is that this class implements the Serializable interface
    • Attributes modified by static are not serialized
  • Use the default methods writeObject and readObject
    • These two methods are defined in a class that implements the Serializable interface
    • Both methods must be private   void modifier, otherwise it will not take effect
    • The writeObject method is used to customize the content and order of serialization
    • The readObject method is used to customize the content and order of deserialization, which should be consistent with the content order of the writeObject method

 

  • Implement Externalizable interface
    • The Externalizable interface inherits from the Serializable interface
    • Two methods need to be overridden
      • writeExternal
        • Input parameter ObjectOutput   out
        • Use out.writeObject (property name) to specify the property to be serialized
      • readExternal
        • Input ObjectInput   in
        • Use in.readObject() to obtain the property value after deserialization, which should be consistent with the sequence of serialized properties

3. Examples

a. Properties that validate transient and static modifiers cannot be serialized

Properties that validate transient and static modifiers cannot be serialized

  • Define the Person class and implement the Serializable interface. among
    • a attribute is decorated with transient (unable to be serialized), b attribute is decorated with static (unable to be serialized), and c attribute is defined normally (can be serialized)
package SerializableTest;

import java.io.Serializable;

public class Person implements Serializable {
    //Cannot be serialized using transient decoration
    private transient String a;
    private static String b;
    private String c;

    @Override
    public String toString() {
        return "Person{" +
                "a='" + a + '\'' +
                ", b='" + b + '\'' +
                ", c='" + c + '\'' +
                '}';
    }

    public String getA() {
        return a;
    }

    public void setA(String a) {
        this.a = a;
    }

    public static String getB() {
        return b;
    }

    public static void setB(String b) {
        Person.b = b;
    }

    public String getC() {
        return c;
    }

    public void setC(String c) {
        this.c = c;
    }
}
  • Define serialization tool classes
package SerializableTest;

import java.io.*;

public class SerializableUtils {
    //Serialization operation
    public static void mySerializable(Object obj,String fileName) throws IOException {
        FileOutputStream fos = new FileOutputStream(fileName);
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(obj);
        oos.close();
        fos.close();
    }

    //Deserialization operation
    public static Object myDesSerializable(String fileName) throws IOException, ClassNotFoundException {
        FileInputStream fis = new FileInputStream(fileName);
        ObjectInputStream ois = new ObjectInputStream(fis);
        Object o = ois.readObject();
        return o;
    }
}
  • Define test class
package SerializableTest;

import java.io.IOException;

public class test {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Person p = new Person();
        p.setA("A");
        Person.setB("B");
        p.setC("C");
        System.out.println("Before serialization p Object:"+p); //Person{a='A', b='B', c='C'}
        //Serialization operation
        SerializableUtils.mySerializable(p,"I:\\a.txt");
        //Modifying the value of b attribute will not affect the value of b attribute in a.txt file
        Person.setB("bbbb");
        //Deserialization operation
        Object o = SerializableUtils.myDesSerializable("I:\\a.txt");
        if (o instanceof Person){
            p = (Person) o;
        }
        //B is static modified. If it can be serialized, the result should still be B, but the result here is bbb, indicating that static modification cannot be serialized
        //A is null, indicating that the a attribute was not serialized during the serialization operation
        System.out.println("Serialized p Object:"+p); //Person{a='null', b='bbbb', c='C'}
    }
}
  • After testing, it is found that the attributes modified by transient and static cannot be instantiated

b. Verify that the serialized properties are specified using the default methods writeObject and readObject

Verify that the serialized properties are specified using the default methods writeObject and readObject

  • The Serializable interface is implemented by default
  • Rewrite the Person class so that a and b are serialized and c is not serialized
package SerializableTest;

import java.io.IOException;
import java.io.Serializable;

public class Person implements Serializable {
    //Cannot be serialized using transient decoration
    private String a;
    private String b;
    private String c;

    private void writeObject(java.io.ObjectOutputStream out) throws IOException {
        //Serialize a and b attributes, not c attributes
        System.out.println("writeObject Serialization processing...");
        out.writeObject(a);
        out.writeObject(b);
    }

    private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
        //Deserialization reads the values of the a and b attributes
        System.out.println("readObject Deserialize...");
        a = (String) in.readObject();
        b = (String) in.readObject();
    }

    @Override
    public String toString() {
        return "Person{" +
                "a='" + a + '\'' +
                ", b='" + b + '\'' +
                ", c='" + c + '\'' +
                '}';
    }

    public String getA() {
        return a;
    }

    public void setA(String a) {
        this.a = a;
    }

    public String getB() {
        return b;
    }

    public void setB(String b) {
        this.b = b;
    }

    public String getC() {
        return c;
    }

    public void setC(String c) {
        this.c = c;
    }
}
  • Tool class unchanged
  • Test class
package SerializableTest;

import java.io.IOException;

public class test {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Person p = new Person();
        p.setA("A");
        p.setB("B");
        p.setC("C");
        System.out.println("Before serialization p Object:"+p); //Person{a='A', b='B', c='C'}
        //Serialization operation
        SerializableUtils.mySerializable(p,"I:\\a.txt");
        //Modifying the value of b attribute will not affect the value of b attribute in a.txt file
        p.setB("bbbb");
        //Deserialization operation
        Object o = SerializableUtils.myDesSerializable("I:\\a.txt");
        if (o instanceof Person){
            p = (Person) o;
        }
        //B is static modified. If it can be serialized, the result should still be B, but the result here is bbb, indicating that static modification cannot be serialized
        //A is null, indicating that the a attribute was not serialized during the serialization operation
        System.out.println("Serialized p Object:"+p); //Person{a='null', b='bbbb', c='C'}
    }
}
  • test result
    • It can be seen that c really cannot be serialized

c. Verify the serialization part properties of the Externalizable interface

Verify the serialization part properties of the Externalizable interface

  •   Modify the Person class, implement the Externalizable interface, and override the two methods
package SerializableTest;

import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;

public class Person implements Externalizable {
    //Cannot be serialized using transient decoration
    private String a;
    private String b;
    private String c;

    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        System.out.println("writeExternal Serialize operation...");
        out.writeObject(a);
        out.writeObject(b);
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        System.out.println("readExternal Perform deserialization...");
        a = (String) in.readObject();
        b = (String) in.readObject();
    }

    @Override
    public String toString() {
        return "Person{" +
                "a='" + a + '\'' +
                ", b='" + b + '\'' +
                ", c='" + c + '\'' +
                '}';
    }

    public String getA() {
        return a;
    }

    public void setA(String a) {
        this.a = a;
    }

    public String getB() {
        return b;
    }

    public void setB(String b) {
        this.b = b;
    }

    public String getC() {
        return c;
    }

    public void setC(String c) {
        this.c = c;
    }
}
  • Tool classes remain unchanged
  • Test class
package SerializableTest;

import java.io.IOException;

public class test {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Person p = new Person();
        p.setA("A");
        p.setB("B");
        p.setC("C");
        System.out.println("Before serialization p Object:"+p); //Person{a='A', b='B', c='C'}
        //Serialization operation
        SerializableUtils.mySerializable(p,"I:\\a.txt");
        //Modifying the value of b attribute will not affect the value of b attribute in a.txt file
        p.setB("bbbb");
        //Deserialization operation
        Object o = SerializableUtils.myDesSerializable("I:\\a.txt");
        if (o instanceof Person){
            p = (Person) o;
        }
        //B is static modified. If it can be serialized, the result should still be B, but the result here is bbb, indicating that static modification cannot be serialized
        //A is null, indicating that the a attribute was not serialized during the serialization operation
        System.out.println("Serialized p Object:"+p); //Person{a='null', b='bbbb', c='C'}
    }
}
  • test result
    • c is not serialized, indicating that the implementation of the Externalizable interface can also realize the serialization of some attributes

  d. The difference between Serializable interface and Externalizable interface

differenceSerializableExternalizable
Implementation complexityThe implementation is simple, and java has built-in supportThe implementation is complex and is completed by developers themselves
Execution efficiencyAll attributes are saved uniformly by java, with low performanceDevelopers can improve execution efficiency by deciding which attributes the object saves
Occupied spaceLarge space for saving dataPartial storage, occupying relatively small space
Frequency of usehighLow

3, Implement deserialization

  • Read the previously serialized stored object from the file and change it into an object in the program again
  • ObjectInputStream used
    • An InputStream object needs to be passed in
  • See the example of implementing serialization for an example

Posted by cyberdesi on Mon, 08 Nov 2021 02:57:50 -0800