Object serialization in the Java tutorial using the basic example

  • 2020-04-01 02:54:55
  • OfStack

This process can also be done over the network by creating an object on a Windows machine, serializing it, then sending it over the network to a Unix machine, where it can be reassembled without error. Like RMI, Socket, JMS, EJB, one of them, the ability to pass Java objects to each other is, of course, the result of the object serialization mechanism.  

The Java object serialization mechanism generally serves two purposes:

JavaBeans of Java: the state information of beans is usually configured at design time, and the state information of beans must be saved so that it can be recovered when the program runs. This requires saving the state of the object to a file, and then being able to reconstruct the object and restore the state of the program by reading in the state of the object.
RMI allows you to manipulate objects on remote machines as if they were on your own machine. These are required to implement the serializaiton mechanism for programs that use sockets to transfer objects over the network.
We can serialize the class by having the class implement the java.io.Serializable interface. The interface is a maker (marker) interface. That is, the interface does not need to implement any methods for the class to implement it. It is primarily used to notify the Java virtual machine (JVM) that an object needs to be serialized.

There are a few things we need to be clear about this:

Not all classes can be serialized, under CMD, we input serialver Java.net.Socket, can get the socket serializable information, socket is actually not serializable.
Many base classes in Java already implement the serializable interface, such as string, vector, and so on. But hashtable, for example, does not implement the serializable interface.
There are two main classes that read or write objects into the stream: ObjectOutputStream and ObjectInputStream.ObjectOutputStream provides the writeObject method to write objects to the output stream, and ObjectInputStream provides the readObject method to read objects from the input stream. Objects that use these methods must already be serialized. That is, you must have implemented the Serializable interface. If you want to write eobject a hashtable object, then you get an exception.
Serialization is the process of writing an object to and reading an object from a byte stream. After converting the object state to a byte stream, you can use the various byte stream classes in the java.io package to save it to a file, pipe it to another thread, or send object data to another host over a network connection. Object serialization is simple and powerful, and is used in RMI, Socket, JMS, and EJB. Object serialization is not the most exciting topic in network programming, but it is very important and has many practical implications.
Object serialization enables distributed objects. For example, RMI USES object serialization to run services on a remote host, just as it does when running objects on a local machine.
Java object serialization not only preserves the data of one object, but also recursively stores the data of each object that the object references. The entire object hierarchy can be written to a byte stream, saved in a file, or passed over a network connection. Object serialization enables "deep copying" of objects, that is, copying the object itself and the referenced object itself. Serializing an object may result in an entire sequence of objects.
Java serialization is simple and usually requires no custom code to save and restore object state. Class objects that implement the java.io.Serializable interface can be converted to or recovered from a byte stream without adding any code to the class. Only rarely does custom code need to save or restore object state. Note that not every class is serializable, and some classes are not serializable, such as classes involving threads that have very complex relationships with a particular JVM.

Serialization mechanism:

Serialization is divided into two major parts: serialization and deserialization. Serialization is the first part of the process, breaking the data into byte streams for storage in a file or transfer over a network. Deserialization is simply opening the byte stream and refactoring the object. Object serialization not only converts the base data type to a byte representation, but also sometimes restores the data. Recovering data requires an object instance of the recovered data. The serialization process in the ObjectOutputStream connects to the byte stream, including object type and version information. When deserialized, the JVM generates an object instance with header information and then copies the data in the object byte stream into the object data member. Here are two parts:

Handle object flow :( Serialization and deserialization)
The java.io package has two classes that serialize objects. The ObjectOutputStream is responsible for writing the object to the stream, and the ObjectInputStream reconstructs the object from the stream.
Let's start with the ObjectOutputStream class. 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 those objects. Each ObjectOutputStream maintains a serialized object reference table, preventing multiple copies of the same object from being sent. (this is important) because writeObject() serializes an entire set of cross-referenced objects, the same ObjectOutputStream instance may accidentally be requested to serialize the same object. Instead of writing to the object byte stream again, deserialize the reference.

Now, let's look at the ObjectOutputStream class from the example.


//Serialize 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 look at the ObjectInputStream class. It's similar to an ObjectOutputStream. It extends the DataInput interface. The method in the ObjectInputStream mirrors the public method in the DataInputStream that reads the Java basic data type. The readObject() method deserializes the object from the 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. When readObject() receives an object, the JVM loads the class specified in the header. If the class cannot be found, readObject() throws a ClassNotFoundException, or if object data and bytecode need to be transferred, the RMI framework can be used. The rest of the ObjectInputStream methods are used to customize the deserialization process.
Here are some examples:

//Deserialize the string object and the date object & NBSP; from the file;
FileInputStream  in = new  FileInputStream ("tmp" );  
ObjectInputStream  s = new  ObjectInputStream (in);  
String  today = (String )s.readObject();  
Date  date = (Date )s.readObject(); 


Customized serialization process:
Serialization is usually done automatically, but sometimes this process may need to be controlled. Java can declare a class as serializable, but you can still manually control data members declared 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 the class should be serializable except those declared transient or static. Declaring a variable as transient tells the JVM that we're responsible for serializing the argument. After declaring the data member as transient, the serialization process cannot add it to the object byte stream, and there is no data sent from the transient data member. Later, when the data is deserialized, the data member is rebuilt (because it is part of the class definition), but contains no data because the data member does not write any data to the stream. Remember that object streams do not serialize static or transient. Our class USES the writeObject() and readObject() methods to handle these data members. When using the writeObject() and readObject() methods, be careful to read the data members in the order they are written.
Part of the code for how to use custom serialization is as follows

//Override the writeObject() method to handle the transient's members.  
public  void  writeObject(ObjectOutputStream  outputStream) throws  IOException {  
outputStream.defaultWriteObject();//Makes a custom writeObject() method available & NBSP;
//Leverage the logic built into 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 () supplement automatic serialization & sending;
InetAddress  oAddress=(InetAddress )inputStream.readObject();  
int  iPort =inputStream.readInt();  
oSocket = new  Socket (oAddress,iPort);  
iID=getID();  
dtToday =new  Date ();  
}  


Fully customized serialization process:
If a class is fully responsible for its own serialization, implement the Externalizable interface instead of the Serializable interface. The Externalizable interface definition includes two methods, writeExternal() and readExternal(). When a class implements Externalizable, the header is written into the object stream, and the class is then fully responsible for serializing and restoring the data members, with no automatic serialization at all except for the header. Here's the thing to watch out for. Declaring the class to implement the Externalizable interface poses a significant security risk. The writeExternal() and readExternal() methods are declared public and can be used by malicious classes to read and write object data. Be extra careful if the object contains sensitive information. This includes using secure sockets or encrypting the entire byte stream. So far, we have learned the basics of serialization.


Related articles: