Why do some Java classes implement serializable interfaces

Source: Internet
Author: User
What is the serializable interface.

An object-serialized interface in which a class can be serialized only if it implements the serializable interface.

What is serialization.

The process of converting the state information of an object into a form that can be stored or transmitted, during serialization, an object writes its current state to a temporary or persistent store, and then the object can be re-created by reading or deserializing the object's state information from the store.

What circumstances require serialization.

When we need to transfer the state information of the object over the network, or we need to persist the state information of the object for future use, we need to serialize the object.


Serializable is mainly used to support two main features:

1. Java RMI (remote method invocation), RMI allows you to manipulate objects on a remote machine as you would on this computer, and when sending a message to a remote object, you need to use a serialization mechanism to send parameters and accept return values

2, the Java Javabean,bean state information is usually configured at design time, the bean's state information must be saved so that when the program is run to restore these state information, this also requires the sequence serializable mechanism

Reproduced



The Java serialization technology that serializes Java objects into binaries is one of the more important technical points in the Java family of technologies, and in most cases developers only need to understand that the serialized class needs to implement the Serializable interface, using ObjectInputStream and O Bjectoutputstream to read and write objects. However, in some cases, it is not enough to know these, the article lists some of the real situation I encountered, they are related to Java serialization, through the analysis of the reasons for the situation, so that readers can easily remember the Java serialization of some high-level understanding.


--------------------------------------------------------------------------------
Back to the top of the page
Article structure

This article will introduce a few scenarios, in the order of the following list.

• The problem of serializing IDs
• Static variable serialization
• Serialization of the parent class and Transient keywords
• Encrypt sensitive fields
• Serialization of storage rules
Each part of the list tells a separate situation that the reader can view separately.


--------------------------------------------------------------------------------
Back to the top of the page
Serialization ID problem

Situation: Two clients A and B try to pass the object data through the network, and a end converts the object C to binary data and then to the b,b deserialization to get C.

Problem: The C object's full class path is assumed to be com.inout.Test, and there is a class file on both a and B terminals, and the functional code is exactly the same. Also implements the Serializable interface, but it always prompts unsuccessfully when deserializing.

Workaround: Whether the virtual machine allows deserialization, depending on whether the classpath and functional code are consistent, a very important point is whether the serialization IDs of two classes are consistent (that is, private static final long Serialversionuid = 1L). In Listing 1, although the functional code for the two classes is exactly the same, the serialization IDs are different and they cannot be serialized and deserialized with each other.


Listing 1. Class comparison of different serialization IDs for the same functional code

Package com.inout;

Import java.io.Serializable;

public class A implements Serializable {

Private static final long serialversionuid = 1L;

private String name;

Public String GetName ()
{
return name;
}

public void SetName (String name)
{
THIS.name = name;
}
}

Package com.inout;

Import java.io.Serializable;

public class A implements Serializable {

Private static final long serialversionuid = 2L;

private String name;

Public String GetName ()
{
return name;
}

public void SetName (String name)
{
THIS.name = name;
}
}



The serialization ID provides two build strategies under Eclipse. One is fixed 1L and one is randomly generating a long type of data that is not duplicated (it is actually generated using JDK tools), and here's a suggestion that if there is no special need, it can be done with the default 1L, which ensures that the code is consistent When deserialization succeeds. So what does a randomly generated serialization ID do, sometimes, by changing the serialization ID to restrict the use of some users.

Feature usage Cases

Readers should have heard of the Façade mode, which provides a unified access interface for applications, which is used by client clients in case programs, and the case program structure diagram is shown in Figure 1.


Figure 1. Case Program Structure


The client side can interact with the business logic object by Façade object. While the client's Façade object cannot be generated directly by client, it needs Server-side generation, and then serializes the binary object data to the client,client over the network to get the Façade object. This pattern allows client-side programs to be used with server-side licensing, while client-side and server-side Façade Object classes need to be aligned. When the server side wants a version update, as long as the serialization ID of the server-side Façade object class is generated again, when the client side deserializes the Façade object fails, that is, the client side is forced to get the latest program from the server side.


--------------------------------------------------------------------------------
Back to the top of the page
Static variable serialization

Context: View the code in Listing 2.


Listing 2. Static variable serialization problem code

public class Test implements Serializable {

Private static final long serialversionuid = 1L;

public static int staticvar = 5;

public static void Main (string[] args) {
try {
Initial Staticvar to 5
ObjectOutputStream out = new ObjectOutputStream (
New FileOutputStream ("Result.obj"));
Out.writeobject (New Test ());
Out.close ();

Modified to 10 after serialization
Test.staticvar = 10;

ObjectInputStream oin = new ObjectInputStream (New FileInputStream (
"Result.obj"));
Test T = (test) oin.readobject ();
Oin.close ();

Read again, print new value via T.staticvar
System.out.println (T.staticvar);

catch (FileNotFoundException e) {
E.printstacktrace ();
catch (IOException e) {
E.printstacktrace ();
catch (ClassNotFoundException e) {
E.printstacktrace ();
}
}
}



The Main method in Listing 2, after serializing the object, modifies the value of the static variable, reads the serialized object, and then obtains the value of the static variable by the object being read and prints it out. According to Listing 2, the SYSTEM.OUT.PRINTLN (T.STATICVAR) statement outputs 10 or 5.

The final output is 10, for the incomprehensible reader that the printed Staticvar is obtained from the object being read, and should be the state of the Save. The reason for printing 10 is that when serializing, the static variable is not saved, which is actually easier to understand, the serialization holds the state of the object, the static variable belongs to the state of the class, so serialization does not save the static variable.


--------------------------------------------------------------------------------
Back to the top of the page
Serialization of the parent class and the Transient keyword

Context: A subclass implements the Serializable interface, its parent class does not implement the Serializable interface, serializes the subclass object, and then deserializes the value of a variable that is defined by the parent class, and the value of the variable is different from the serialized value.

Workaround: To serialize the parent class object, you need to have the parent class implement the Serializable interface as well. If the parent class is not implemented, a default parameterless constructor is required. When the parent class does not implement the Serializable interface, the virtual machine does not serialize the parent object, and the construction of a Java object must have a parent object before the child object, and deserialization is no exception. So when deserializing, in order to construct the parent object, only the parent class's parameterless constructor can be invoked as the default parent object. So when we take the variable value of the parent object, its value is the value after calling the parent class parameterless constructor. If you take this serialization into account, initialize the variable in the parent class parameterless constructor, otherwise the parent class variable value is the default declared value, such as the default of type int is null by default for 0,string type.

The role of the Transient keyword is to control the serialization of variables, by adding the keyword before the variable declaration, you can prevent the variable from being serialized to a file and, after being deserialized, the value of the Transient variable is set to the initial value, such as 0 for the int, and NULL for the object type.

Feature usage Cases

We are familiar with the use of the Transient keyword can make the field is not serialized, then there are other ways. The rule that is serialized according to the parent class object, we can extract the fields that do not need to be serialized into the parent class, the subclass implements the Serializable interface, the parent class does not implement, and the parent class's field data is not serialized according to the parent class serialization rule, and the class diagram is shown in Figure 2.


Figure 2. Case Program Class diagram


As can be seen in the figure above, ATTR1, ATTR2, ATTR3, ATTR5 are not serialized, the advantage of placing in the parent class is that when there is another child class, ATTR1, ATTR2, Attr3 are still not serialized, do not repeat the transient, code concise.


--------------------------------------------------------------------------------
Back to the top of the page
Encrypt sensitive fields

Context: Server-side sends serialized object data to client, some of the data in the object is sensitive, such as a password string, which you want to encrypt when serializing the password field, and if the client has the decrypted key, the password can be read only when the client is deserializing. This ensures a certain degree of data security for the serialized object.

Workaround: In the serialization process, the virtual opportunity attempts to invoke the WriteObject and ReadObject methods in the object class for user-defined serialization and deserialization, and if there is no such method, the default call is ObjectOutputStream Defaultwriteobject method and the Defaultreadobject method of ObjectInputStream. User-defined WriteObject and ReadObject methods allow users to control the serialization process, such as dynamically changing serialized values during serialization. Based on this principle, can be used in practical applications, for sensitive field encryption work, listing 3 shows this process.


Listing 3. Static variable serialization problem code

Private static final long serialversionuid = 1L;

Private String Password = "Pass";

Public String GetPassword () {
return password;
}

public void SetPassword (String password) {
This.password = password;
}

private void WriteObject (ObjectOutputStream out) {
try {
Putfield putfields = Out.putfields ();
System.out.println ("Original password:" + password);
Password = "Encryption";//Analog encryption
Putfields.put ("password", password);
SYSTEM.OUT.PRINTLN ("Encrypted password" + password);
Out.writefields ();
catch (IOException e) {
E.printstacktrace ();
}
}

private void ReadObject (ObjectInputStream in) {
try {
GetField readfields = In.readfields ();
Object = Readfields.get ("Password", "");
System.out.println ("The string to decrypt:" + object.tostring ());
Password = "Pass";//simulate decryption, need to obtain local key
catch (IOException e) {
E.printstacktrace ();
catch (ClassNotFoundException e) {
E.printstacktrace ();
}

}

public static void Main (string[] args) {
try {
ObjectOutputStream out = new ObjectOutputStream (
New FileOutputStream ("Result.obj"));
Out.writeobject (New Test ());
Out.close ();

ObjectInputStream oin = new ObjectInputStream (New FileInputStream (
"Result.obj"));
Test T = (test) oin.readobject ();
System.out.println ("decrypted string:" + T.getpassword ());
Oin.close ();
catch (FileNotFoundException e) {
E.printstacktrace ();
catch (IOException e) {
E.printstacktrace ();
catch (ClassNotFoundException e) {
E.printstacktrace ();
}
}



In Listing 3, the WriteObject method encrypts the password and decrypts the password in ReadObject, only the client with the key can parse the password correctly and ensure the security of the data. The console output, as shown in Figure 3, is performed after listing 3.


Figure 3. Data Encryption Demo


Feature usage Cases

RMI technology is completely based on Java serialization technology, server-side interface calls the required parameter objects to the client, they are transmitted through the network. This involves the issue of RMI's secure transmission. Some sensitive fields, such as user name password (the user needs to be transferred to the password), we want to encrypt it, at this time, you can use the method described in this section in the client to encrypt the password, the server to decrypt, to ensure the security of data transmission.


--------------------------------------------------------------------------------
Back to the top of the page
Serialization of storage rules

Context: The problem code is shown in Listing 4.


Listing 4. Storage Rule Problem Code

ObjectOutputStream out = new ObjectOutputStream (
New FileOutputStream ("Result.obj"));
Test test = new test ();
Attempt to write object two times to file
Out.writeobject (test);
Out.flush ();
System.out.println (New File ("Result.obj"). Length ());
Out.writeobject (test);
Out.close ();
System.out.println (New File ("Result.obj"). Length ());

ObjectInputStream oin = new ObjectInputStream (New FileInputStream (
"Result.obj"));
Read two files sequentially from a file
Test T1 = (test) oin.readobject ();
Test t2 = (test) oin.readobject ();
Oin.close ();

Determine if two references point to the same object
System.out.println (t1 = = t2);



The same object is written two times in Listing 3, prints out the storage size after the object is written once, and the storage size after two times, and then deserializes two objects from the file to compare whether the two objects are the same object. The general thinking is that two times to write the object, the file size will be twice times the size of the deserialization, as a result of reading from the file, generated two objects, the equality should be judged by the input false, but the final result output as shown in Figure 4.


Figure 4. Sample program Output


We see that the file only adds 5 bytes to the second time the object is written, and that two objects are equal.

Solution: Java serialization mechanism to save disk space, with a specific storage rule, when a file is written to the same object, the contents of the object are not stored, but only a reference is stored again, and the 5-byte storage space added above is the space for new references and some control information. When deserializing, the reference relationship is resumed so that the T1 and T2 in Listing 3 point to a unique object, which is equal and outputs true. This storage rule saves a lot of storage space.

Characteristic case analysis

Look at the code in Listing 5.


Listing 5. Case code

ObjectOutputStream out = new ObjectOutputStream (New FileOutputStream ("Result.obj"));
Test test = new test ();
TEST.I = 1;
Out.writeobject (test);
Out.flush ();
TEST.I = 2;
Out.writeobject (test);
Out.close ();
ObjectInputStream oin = new ObjectInputStream (New FileInputStream (
"Result.obj"));
Test T1 = (test) oin.readobject ();
Test t2 = (test) oin.readobject ();
System.out.println (T1.I);
System.out.println (T2.I);


The purpose of Listing 4 is to save the test object to the Result.obj file two times, write once, modify the value of the object property again, and then read out two objects from the Result.obj, outputting the value of the I property of the two objects. The purpose of the case code is to change the status of a one-time transfer object.

As a result, all two outputs are 1, the reason is that after the first write to the object, and then try to write the second time, the virtual machine according to the reference relationship know that there is already a same object has been written to the file, so only save the second write reference, so read, is the first time to save the object. Readers need to pay special attention to this problem when using a file multiple times writeobject.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.