• 周六. 10 月 12th, 2024

5G编程聚合网

5G时代下一个聚合的编程学习网

热门标签

Java serialization and deserialization, you may ignore the details of knowledge

King Wang

1 月 3, 2022

List of articles

  • Preface
  • One 、 Why serialize
  • Two 、 First look at one Demo
  • 3、 … and 、 Serialized ID
  • Four 、 Parent child class serialization
  • 5、 … and 、 Custom Serialization
  • 6、 … and 、 Storage of multi object serialization
    • 6.1 Write the same object of the same class multiple times
    • 6.2 Write the same object of the same class multiple times ( Modify the attributes one by one )
    • 6.3 Write different objects of the same class multiple times
    • 6.4 Write different objects several times
  • Java Serialization knowledge summary

Preface

When I was learning serialization a long time ago, I wrote an article about Java Serialized blog , But it’s just a simple use , Welcome to move :http://blog.beifengtz.com/article/36. I ran into a serialization problem at work last week , It is the problem of saving the value of parent-child class serialization , There’s a lot of detail about serialization , Let’s study this article carefully Java Serialization in .

One 、 Why serialize

Nowadays, most of the systems in enterprises are not written in single language , A platform may have Java、Python、Cpp、Lua Waiting for the language to be written , If there is data interaction within or between this platform and other platforms , There must be a unified data format , The data of each language must be sequenced into these unified formats before it can be recognized by other systems , The result of general serialization is a binary data , When the receiving system receives the binary data, it must be deserialized and converted into data that it can recognize . Except for network transmission, of course , Serialization is also a means of persistence , You can serialize it into a binary file for data storage . The common serialization formats supported by multiple languages are XML、JSON、ProtoBuf etc. .

Java There are also serialization methods supported by the language , In general, serialization is used in object persistence , Network transmission uses more of the three common serialization formats mentioned above .

Two 、 First look at one Demo

Serialized objects :

/**
* @author beifengtz
* <a href='http://www.beifengtz.com'>www.beifengtz.com</a>
* <p>location: serializ.javase_learning</p>
* Created in 10:41 2019/10/13
*/
public class User implements Serializable {

private static final long serialVersionUID = -6849794470754667710L;
private String name;
private transient String gender;
private int age;
private long regTime;
public User(String name, String gender, int age, long regTime) {

this.name = name;
this.gender = gender;
this.age = age;
this.regTime = regTime;
}
public User(String name, int age, long regTime) {

this.name = name;
this.age = age;
this.regTime = regTime;
}
@Override
public String toString() {

return "User{" +
"name='" + name + '\'' +
", gender='" + gender + '\'' +
", age=" + age +
", regTime=" + regTime +
'}';
}
}

Serialization and deserialization :

/**
* @author beifengtz
* <a href='http://www.beifengtz.com'>www.beifengtz.com</a>
* <p>location: serialization.javase_learning</p>
* Created in 10:46 2019/10/13
*/
public class SerializationDemo {

public static void main(String[] args) {

User user = new User("beifengtz", " male ", 100, System.currentTimeMillis() / 1000);
System.out.println(" Before serialization :");
System.out.println(user);
// Serialize objects into files 
ObjectOutputStream oos = null;
try {

oos = new ObjectOutputStream(new FileOutputStream("serFile"));
oos.writeObject(user);
} catch (IOException e) {

e.printStackTrace();
} finally {

try {

assert oos != null;
oos.close();
} catch (IOException e) {

e.printStackTrace();
}
}
// Deserialize from a file to an object 
File file = new File("serFile");
ObjectInputStream ois = null;
try {

ois = new ObjectInputStream(new FileInputStream(file));
User serUser = (User) ois.readObject();
System.out.println(" After serialization :");
System.out.println(serUser);
} catch (IOException | ClassNotFoundException e) {

e.printStackTrace();
} finally {

try {

assert ois != null;
ois.close();
} catch (IOException e) {

e.printStackTrace();
}
}
}
}

The result of the final console output :

 Before serialization :
User{name='beifengtz', gender=' male ', age=100, regTime=1570935427}
After serialization :
User{name='beifengtz', gender='null', age=100, regTime=1570935427}

Then let’s look at the serialization file generated in the middle serFile, Open it directly and it’s garbled , Open it with binary editor and it’s full of 16 Hexadecimal characters .

3、 … and 、 Serialized ID

Serializer and deserializer want a successful data transfer , Three conditions must be guaranteed :

  1. Class full path must be the same , For example, all of them are com.beifengtz.User
  2. Class function code must be the same
  3. serialize ID It has to be the same , For example, all of them are private static final long serialVersionUID = 1L

None of the above three conditions can be serialized successfully , If serialization is not defined ID The virtual opportunity randomly generates a ID, But this is not very controllable for the program , After all, serialization serves multiple ends . Here’s one IBM Developer An example from an article in , Use cases in practical application :

Facade In the pattern ,Facade Object Is to provide a unified access interface for applications , In the case procedure Client The client uses this mode , The structure of the case procedure is shown in the figure :

https://www.ibm.com/developerworks/cn/java/j-lo-serial/image003.gif

Client End pass Façade Object To interact with business logic objects . And on the client side Façade Object Not directly from Client Generate , But needs Server End generation , And then serialize the binary object data through the network to Client,Client Responsible for deserializing to get Façade object . This mode enables Client The use of the end program requires the permission of the server , meanwhile Client End and server end Façade Object Class needs to be consistent . When the server wants to make a version update , Just put the server-side Façade Object Serialization of classes ID Generate… Again , When Client End deserialization Façade Object Will fail , That is to say, compulsion Client Get the latest program from the server .

Four 、 Parent child class serialization

  1. Serialization , Save only the state of the object , Regardless of the object’s method ;
  2. The parent class implements Serializable, Subclasses automatically implement serialization , When serializing subclasses , The property value of the parent class will also be saved , So subclasses don’t need to show the implementation Serializable;
  3. The parent class does not implement Serializable, Subclass implementation Serializable, When serializing subclasses , The property value of the parent class Will not be saved , And the parent class must have no parameter construction ( Because there is no parent property value when deserializing , When instantiating an object, there are only subclass property values ).

Let’s not write practical examples here , If you are interested, you can verify it by yourself .

5、 … and 、 Custom Serialization

During serialization , The virtual machine tries to call the writeObject and readObject Method , User defined serialization and deserialization , If there is no such way , The default call is ObjectOutputStream Of defaultWriteObject Methods and ObjectInputStream Of defaultReadObject Method . User defined writeObject and readObject Method allows the user to control the serialization process , For example, the value of serialization can be changed dynamically during serialization .

Take a look at the following example :

public class Test implements Serializable {

private static final long serialVersionUID = 1L;
private String account = "beifengtz";
private String password = "123456";
public String getAccount() {

return account;
}
public String getPassword() {

return password;
}
private void readObject(ObjectInputStream in) {

try {

System.out.println("------ Start deserializing ------");
ObjectInputStream.GetField readField = in.readFields();
Object obj = readField.get("password", "");
System.out.println(" Password to decrypt :" + obj);
password = String.valueOf(Integer.parseInt((String) obj) / 1000);
System.out.println(" Decrypted password :" + password);
System.out.println("------ End of deserialization ------");
} catch (IOException | ClassNotFoundException e) {

e.printStackTrace();
}
}
private void writeObject(ObjectOutputStream out) {

try {

System.out.println("------ Start serializing ------");
ObjectOutputStream.PutField putField = out.putFields();
String encrypt = String.valueOf(Integer.parseInt(password) * 1000);
putField.put("password", encrypt);
putField.put("account", account);
System.out.println(" Real password :" + password);
System.out.println(" Encrypted password :" + encrypt);
out.writeFields();
System.out.println("------ End of serialization -----");
} catch (IOException e) {

e.printStackTrace();
}
}
public static void main(String[] args) {

try {

ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("serFile"));
out.writeObject(new Test());
out.close();
ObjectInputStream in = new ObjectInputStream(new FileInputStream("serFile"));
Test test = (Test) in.readObject();
in.close();
System.out.println(" Password received after deserialization :" + test.getPassword());
} catch (IOException | ClassNotFoundException e) {

e.printStackTrace();
}
}
}

Look at the results

------ Start serializing ------
Real password :123456
Encrypted password :123456000
------ End of serialization -----
------ Start deserializing ------
Password to decrypt :123456000
Decrypted password :123456
------ End of deserialization ------
Password received after deserialization :123456

6、 … and 、 Storage of multi object serialization

about JDK Serialization of is not simply a binary text append store , But there are some optimizations . Its multi object serialization storage method is as follows :

  1. If objects stored multiple times are objects of different classes , The serialized binary content is appended directly to the text ;
  2. If the object stored multiple times is the same object of the same class , And its properties are exactly the same , After writing binary for the first time , The subsequent serialization only holds reference and control information , The rest of the same information is reused , It’s not a text addition ;
  3. If the object stored multiple times is the same object of the same class , However, the object contents are changed during multiple writes , The virtual machine knows that a same object has been written to the file according to the reference relationship , Save only the first written object , The object modification after the first serialization cannot be saved ;
  4. If the objects stored multiple times are different objects of the same class , Class information is also reused in serialization , Only the reference and control information of different properties of different objects are saved , Reuse the same properties .

Take a look at the following four different scenarios , Have you ever met ?

The following four scenarios are based on the following two classes for serialization testing :

Test1 class

public class Test1 implements Serializable {

private Integer value;
public Test1(Integer value) {

this.value = value;
}
@Override
public String toString() {

return "Test1{" +
"value=" + value +
'}';
}
}

Test2 class

public class Test2 implements Serializable {

private String content;
public Test2(String content) {

this.content = content;
}
public void setContent(String content) {

this.content = content;
}
@Override
public String toString() {

return "Test2{" +
"content='" + content + '\'' +
'}';
}
}

6.1 Write the same object of the same class multiple times

Examples :

public static void main(String[] args) {

try {

ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("serFile"));
Test2 test = new Test2("1");
out.writeObject(test);
out.flush();
System.out.println(" Binary file length :" + new File("serFile").length());
out.writeObject(test);
out.flush();
out.close();
System.out.println(" Binary file length :" + new File("serFile").length());
} catch (IOException e) {

e.printStackTrace();
}
try {

ObjectInputStream in = new ObjectInputStream(new FileInputStream("serFile"));
Test2 test_1 = (Test2) in.readObject();
Test2 test_2 = (Test2) in.readObject();
System.out.println(test_1);
System.out.println(test_2);
System.out.println(test_1 == test_2);
} catch (IOException | ClassNotFoundException e) {

e.printStackTrace();
}
}

Execution results :

 Binary file length :75
Binary file length :80
Test2{content='1'}
Test2{content='1'}
true

6.2 Write the same object of the same class multiple times ( Modify the attributes one by one )

Examples :

public static void main(String[] args) {

try {

ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("serFile"));
Test2 test = new Test2("1");
out.writeObject(test);
out.flush();
System.out.println(" Binary file length :" + new File("serFile").length());
test.setContent("2"); // modify test Property content 
out.writeObject(test);
out.flush();
out.close();
System.out.println(" Binary file length :" + new File("serFile").length());
} catch (IOException e) {

e.printStackTrace();
}
try {

ObjectInputStream in = new ObjectInputStream(new FileInputStream("serFile"));
Test2 test_1 = (Test2) in.readObject();
Test2 test_2 = (Test2) in.readObject();
System.out.println(test_1);
System.out.println(test_2);
System.out.println(test_1 == test_2);
} catch (IOException | ClassNotFoundException e) {

e.printStackTrace();
}
}

Execution results :

 Binary file length :75
Binary file length :80
Test2{content='1'}
Test2{content='1'}
true

6.3 Write different objects of the same class multiple times

Examples :

public static void main(String[] args) {

try {

ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("serFile"));
out.writeObject(new Test2("1"));
out.flush();
System.out.println(" Binary file length :" + new File("serFile").length());
out.writeObject(new Test2("2"));
out.flush();
out.close();
System.out.println(" Binary file length :" + new File("serFile").length());
} catch (IOException e) {

e.printStackTrace();
}
try {

ObjectInputStream in = new ObjectInputStream(new FileInputStream("serFile"));
Test2 test_1 = (Test2) in.readObject();
Test2 test_2 = (Test2) in.readObject();
System.out.println(test_1);
System.out.println(test_2);
System.out.println(test_1 == test_2);
} catch (IOException | ClassNotFoundException e) {

e.printStackTrace();
}
}

Execution results :

 Binary file length :75
Binary file length :85
Test2{content='1'}
Test2{content='2'}
false

6.4 Write different objects several times

Examples :

public static void main(String[] args) {

try {

ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("serFile"));
out.writeObject(new Test1(1));
out.flush();
System.out.println(" Binary file length :" + new File("serFile").length());
out.writeObject(new Test2("2"));
out.flush();
out.close();
System.out.println(" Binary file length :" + new File("serFile").length());
} catch (IOException e) {

e.printStackTrace();
}
try {

ObjectInputStream in = new ObjectInputStream(new FileInputStream("serFile"));
Test1 test_1 = (Test1) in.readObject();
Test2 test_2 = (Test2) in.readObject();
System.out.println(test_1);
System.out.println(test_2);
} catch (IOException | ClassNotFoundException e) {

e.printStackTrace();
}
}

Execution results :

 Binary file length :147
Binary file length :218
Test1{value=1}
Test2{content='2'}

Java Serialization knowledge summary

  1. Objects that need to be serialized must implement Serializable Interface , This is a declarative interface , There are no properties or methods , If the interface is not implemented, an error will be reported :NotSerializableException
  2. adopt ObjectOutputStream and ObjectInputStream Serializing and deserializing objects
  3. By transient The property value decorated by the keyword will not be saved in the serialization file , So the property value after deserialization is the default value of variable type . Here, for example. String Of gender Namely null
  4. Serialization does not save static variables
  5. Whether the virtual machine allows deserialization , Not only depends on whether the class path and function code are consistent , A very important point is the serialization of two classes ID Is it consistent (private static final long serialVersionUID)
  6. For storage of multi object serialization , It’s not a simple binary addition , Virtual machine has some optimization to it , Reduce disk space usage or network transfer content size

发表回复