The process of serialization is the object writes the byte stream and reads the object from the byte stream. After you convert an object state to a byte stream, you can save it to a file with a variety of byte streams in the Java.io package, pipe to another thread, or send the object data to another host over a network connection. Object serialization is very simple and powerful, and is used in RMI, sockets, JMS, and EJBs. The problem of object serialization is not the most exciting subject in network programming, but it is very important and has many practical meanings.
1. Object serialization enables the implementation of distributed objects. Main applications For example: RMI uses object serialization to run a service on a remote host as if it were running on a local machine.
2.Java object serialization not only preserves the data of one object, but also recursively holds the data of each object referenced by the object. The entire object hierarchy can be written to a byte stream and can be saved in a file or passed on a network connection. Object serialization enables the "deep copy" of objects, that is, the copying of objects themselves and the objects they refer to. Serializing an object can get the entire sequence of objects.
From the above description, we know that object serialization is a necessary weapon in Java programming, so let's start with the basics and learn about its mechanism and usage.
Java serialization is simpler and usually requires no custom code to save and recover the state of the object. A class object that only needs to implement an interface (Java.io.Serializable) can be converted to a byte stream or recovered from a byte stream, without adding any code to the class. In rare cases, custom code is required to save or restore object state. Note here: Not every class is serializable, and some classes are not serializable, for example, a class involving threads has a very complex relationship with a particular JVM.
Serialization mechanism:
Serialization is divided into two parts: serialization and deserialization. Serialization is the first part of the process that decomposes data into byte streams for storage in files or on the network. Deserialization is the opening of a byte stream and the construction of an object. Object serialization not only converts basic data types to byte representations, but sometimes restores data. Recovery data requires an object instance that recovers data. The serialization process in ObjectOutputStream is connected to a byte stream, including the object type and version information. When deserialized, the JVM generates an object instance with the header information, and then copies the data in the object byte stream to the object data member. Here are two major sections to illustrate:
Process Object Flow: (serialization process and deserialization process)
The Java.io package has two classes of serialized objects. ObjectOutputStream is responsible for writing the object to the byte stream and ObjectInputStream the object from the byte stream.
Let's get to the ObjectOutputStream class first. The ObjectOutputStream class extends the DataOutput interface.
The WriteObject () method is the most important method for object serialization. If the object contains references to other objects, the WriteObject () method recursively serializes the objects. Each ObjectOutputStream maintains a serialized object reference table, preventing multiple copies of the same object from being sent. (This is important) because WriteObject () can serialize an entire set of cross-referenced objects, the same ObjectOutputStream instance may be accidentally requested to serialize the same object. In this case, the deserialization is serialized instead of the object byte stream being written again.
Let's take a look at the ObjectOutputStream class from the examples below.
Serializes today ' s date to a file.
FileOutputStream f = new FileOutputStream ("TMP");
ObjectOutputStream s = new ObjectOutputStream (f);
S.writeobject ("Today");
S.writeobject (New Date ());
S.flush ();
Now, let's take a look at this class of ObjectInputStream. It is similar to the ObjectOutputStream. It extends the Datainput interface. The public method of reading Java basic data types in the method mirror DataInputStream in ObjectInputStream. The ReadObject () method deserializes an object from a byte stream. Each call to the ReadObject () method returns the next object in the stream. The object byte stream does not transmit the bytecode of the class, but includes the class name and its signature. ReadObject () When an object is received, the JVM loads the class specified in the header. If this class is not found, the ReadObject () throws ClassNotFoundException, and if you need to transfer the object data and bytecode, you can use the RMI framework. The remainder of the ObjectInputStream method is used to customize the deserialization process.
Examples are as follows:
Deserializes a string object and a Date object from a file FileInputStream in = new FileInputStream ("TMP"); ObjectInputStream s = new ObjectInputStream (in); String today = (string) s.readobject (); Date date = (date) s.readobject ();
Customizing the serialization process:
Serialization can usually be done automatically, but sometimes this process may have to be controlled. Java can declare a class as serializable, but it can still manually control data members declared as static or transient.
Example: A very simple serialization class.
public class Simpleserializableclass implements Serializable
{
String stoday= "Today:";
Transient date dttoday=new date ();
}
When serialized, all data members of a class should be serializable except for members declared as transient or static. Declaring a variable as transient tells the JVM that we are responsible for serializing the arguments. When a data member is declared as transient, the serialization process cannot be added to the object byte stream, and no data is sent from the transient data member. When the data is deserialized later, the data member is rebuilt (because it is part of the class definition) but does not contain any data because the data member does not write any data to the stream. Remember that the object stream does not serialize static or transient. Our class uses the WriteObject () and ReadObject () methods to process these data members. When using the WriteObject () and ReadObject () methods, also note that the data members are read in the order in which they are written.
Some of the code on how to use custom serialization is as follows:
Override the WriteObject () method to handle the members of the transient.
public void WriteObject (ObjectOutputStream outputstream) throws IOException
{
Outputstream.defaultwriteobject ();
Enables the custom WriteObject () method to take advantage of the logic built into the automatic serialization.
Outputstream.writeobject (Osocket.getinetaddress ());
Outputstream.writeint (Osocket.getport ());
}
Override the ReadObject () method to receive members of the transient.
private void ReadObject (ObjectInputStream inputstream) throws Ioexception,classnotfoundexception
{
Inputstream.defaultreadobject ();//defaultreadobject () Supplemental automatic serialization
InetAddress oaddress= (inetaddress) inputstream.readobject ();
int Iport =inputstream.readint ();
Osocket = new Socket (oaddress,iport);
Iid=getid ();
Dttoday =new Date ();
}
Fully customizable serialization process:
If a class is to be fully responsible for its own serialization, implement the Externalizable interface instead of the serializable interface. The Externalizable interface definition consists of two methods writeexternal () and readexternal (). These methods allow you to control how object data members write to a byte stream. When a class implements Externalizable, the header is written to the object stream, and then the class is fully responsible for serializing and restoring the data member, which is not automatically serialized except for the header. Here you have to pay attention. Declaring a class implements the Externalizable interface can have significant security risks. The Writeexternal () and the Readexternal () method are declared public, and the malicious class can use these methods to read and write object data. Be extra careful if the object contains sensitive information. This includes using Secure Sockets or encrypting entire byte streams.
Process Object Flow: (serialization process and deserialization process)
The Java.io package has two classes of serialized objects. ObjectOutputStream is responsible for writing the object to the byte stream and ObjectInputStream the object from the byte stream.
Let's get to the ObjectOutputStream class first. The ObjectOutputStream class extends the DataOutput interface.
The WriteObject () method is the most important method for object serialization. If the object contains references to other objects, the WriteObject () method recursively serializes the objects. Each ObjectOutputStream maintains a serialized object reference table, preventing multiple copies of the same object from being sent. (This is important) because WriteObject () can serialize an entire set of cross-referenced objects, the same ObjectOutputStream instance may be accidentally requested to serialize the same object. In this case, the deserialization is serialized instead of the object byte stream being written again.
Let's take a look at the ObjectOutputStream class from the examples below.
Serializes today ' s date to a file.
FileOutputStream f = new FileOutputStream ("TMP");
ObjectOutputStream s = new ObjectOutputStream (f);
S.writeobject ("Today");
S.writeobject (New Date ());
S.flush ();
Now, let's take a look at this class of ObjectInputStream. It is similar to the ObjectOutputStream. It extends the Datainput interface. The public method of reading Java basic data types in the method mirror DataInputStream in ObjectInputStream. The ReadObject () method deserializes an object from a byte stream. Each call to the ReadObject () method returns the next object in the stream. The object byte stream does not transmit the bytecode of the class, but includes the class name and its signature. ReadObject () When an object is received, the JVM loads the class specified in the header. If this class is not found, the ReadObject () throws ClassNotFoundException, and if you need to transfer the object data and bytecode, you can use the RMI framework. The remainder of the ObjectInputStream method is used to customize the deserialization process.