Understanding Java serialization and deserialization _java

Source: Internet
Author: User
Tags int size object serialization reflection serialization

The article mainly involves the following several questions:

    • How to implement serialization of Java
    • Why the Java.io.Serializable interface is implemented to be serialized
    • What is the role of transient?
    • How to customize serialization policies
    • How the custom serialization policy is invoked
    • What is the benefit of ArrayList's implementation of serialization

Serialization of Java Objects

The Java platform allows us to create reusable Java objects in memory, but in general, these objects can exist only when the JVM is running, that is, the life cycle of these objects is no longer than the life cycle of the JVM. In real-world applications, however, it is possible to require that the specified object be saved (persisted) after the JVM has stopped running, and that the saved object be re-read in the future. Java object Serialization can help us implement this functionality.

With Java object serialization, when you save an object, it saves its state as a set of bytes, and then assembles the bytes into objects in the future. It is important to note that object serialization holds the object's "state", which is its member variable. Therefore, object serialization does not focus on static variables in the class.

In addition to object serialization when objects are persisted, object serialization is used when using RMI (remote method invocation) or passing objects across the network. The Java Serialization API provides a standard mechanism for processing object serialization, which is easy to use and is described in successive chapters of this article.

public class Arraylist<e> extends abstractlist<e>
    implements List<e>, Randomaccess, Cloneable, Java.io.Serializable
{
  private static final long serialversionuid = 8683452581122892189L;

  Transient object[] elementdata; Non-private to simplify nested class access

  private int size;
}

Ii. how to serialize and deserialize Java objects

In Java, as long as a class implements the Java.io.Serializable interface, it can be serialized. Here's a piece of code first:

Code 1 creates a user class for serialization and deserialization

Package com.hollis;
Import java.io.Serializable;

Import Java.util.Date;
 /** * Created by Hollis on 16/2/2.
  */public class User implements serializable{private String name;
  private int age;
  Private Date birthday;
  private transient String gender;

  Private static final long serialversionuid = -6849794470754667710l;
  Public String GetName () {return name;
  public void SetName (String name) {this.name = name;
  public int getage () {return age;
  public void Setage (int age) {this.age = age;
  Public Date Getbirthday () {return birthday;
  The public void Setbirthday (Date birthday) {this.birthday = birthday;
  Public String Getgender () {return gender;
  } public void Setgender (String gender) {This.gender = gender; 
        @Override public String toString () {return "user{" + "Name= '" + name + ' \ ' + ", age=" + Age +
        ", gender=" + Gender + ", birthday=" + Birthday +'}';

 }
}

Code 2 demo to serialize and deserialize the user

Package com.hollis;
Import Org.apache.commons.io.FileUtils;
Import Org.apache.commons.io.IOUtils;
Import java.io.*;

Import Java.util.Date;
 /** * Created by Hollis on 16/2/2. */public class Serializabledemo {public static void main (string[] args) {//initializes The Object user user
    = new User ();
    User.setname ("Hollis");
    User.setgender ("male");
    User.setage (23);
    User.setbirthday (New Date ());

    SYSTEM.OUT.PRINTLN (user);
    Write Obj to File objectoutputstream oos = null;
      try {oos = new ObjectOutputStream (New FileOutputStream ("Tempfile"));
    Oos.writeobject (user);
    catch (IOException e) {e.printstacktrace ();
    finally {ioutils.closequietly (oos);
    }//read Obj from File File = new file ("Tempfile");
    ObjectInputStream ois = null;
      try {ois = new ObjectInputStream (new FileInputStream (file));
      User NewUser = (user) ois.readobject ();
    System.out.println (NewUser); } catch (IOException e) {e.printstacktrace ();
    catch (ClassNotFoundException e) {e.printstacktrace ();
      finally {ioutils.closequietly (OIS);
      try {fileutils.forcedelete (file);
      catch (IOException e) {e.printstacktrace (); }}}//output//user{name= ' Hollis ', age=23, Gender=male, Birthday=tue Feb ' CST 17:37:38} 2016 ' Ho

 Llis ', age=23, Gender=null, Birthday=tue Feb CST 2016}

Third, serialization and deserialization of related knowledge

1, in Java, as long as a class implements the Java.io.Serializable interface, then it can be serialized.

2, serialization and deserialization of objects through ObjectOutputStream and ObjectInputStream

3, whether the virtual machine allows deserialization, not only depends on the classpath and functional code is consistent, a very important point is that the serialization ID of two classes are consistent (that is, private static final long Serialversionuid)

4. Serialization does not save static variables.

5, want to also serialize the parent class object, need to let the parent class also implement Serializable interface.

6, 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.

7. 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.

Iv. serialization of ArrayList

Before introducing ArrayList serialization, consider a problem:

How to customize serialization and deserialization policies

With this problem, let's look at Java.util.ArrayList's source code.

Code 3

public class Arraylist<e> extends abstractlist<e>
    implements List<e>, Randomaccess, Cloneable, Java.io.Serializable
{
  private static final long serialversionuid = 8683452581122892189L;
  Transient object[] elementdata; Non-private to simplify nested class access
  private int size;
}

The author omits other member variables, from the above code can know that ArrayList implements the Java.io.Serializable interface, then we can serialize and deserialize it. Because Elementdata is transient, we think that this member variable will not be serialized and preserved. Let's write a demo to verify our ideas:

Code 4

public static void Main (string[] args) throws IOException, classnotfoundexception {list<string> stringlist = n
    EW arraylist<string> ();
    Stringlist.add ("Hello");
    Stringlist.add ("World");
    Stringlist.add ("Hollis");
    Stringlist.add ("Chuang");
    System.out.println ("init stringlist" + stringlist);
    ObjectOutputStream ObjectOutputStream = new ObjectOutputStream (New FileOutputStream ("Stringlist"));

    Objectoutputstream.writeobject (stringlist);
    Ioutils.close (ObjectOutputStream);
    File File = new file ("Stringlist");
    ObjectInputStream ObjectInputStream = new ObjectInputStream (new FileInputStream (file));
    List<string> newstringlist = (list<string>) objectinputstream.readobject ();
    Ioutils.close (ObjectInputStream);
    if (file.exists ()) {file.delete ();
  } System.out.println ("New stringlist" + newstringlist);

 //init Stringlist[hello, World, Hollis, Chuang]//new Stringlist[hello, World, Hollis, Chuang]

People who know ArrayList know that the ArrayList bottom is implemented through arrays. So the array elementdata is actually used to save the elements in the list. Through the declaration of this property we know that he cannot be persisted through serialization. So why does the result of code 4 retain the elements in the list by serializing and deserializing it?

V. WriteObject and ReadObject methods

A method is defined in ArrayList: WriteObject and ReadObject.

Here we give the conclusion first:

In the serialization process, if the writeobject and ReadObject methods are defined in the serialized class, the virtual opportunity attempts to invoke the WriteObject and ReadObject methods in the object class, making user-defined serialization and deserialization.

If there is no such method, the default invocation is the ObjectOutputStream Defaultwriteobject method and the ObjectInputStream Defaultreadobject method.

User-defined WriteObject and ReadObject methods allow users to control the serialization process, such as dynamically changing serialized values during serialization.

Take a look at the concrete implementations of these two methods:

Code 5

private void ReadObject (Java.io.ObjectInputStream s)
    throws Java.io.IOException, classnotfoundexception {
    Elementdata = Empty_elementdata;

    Read in size, and any hidden stuff
    s.defaultreadobject ();

    Read in Capacity
    s.readint ()//ignored

    if (Size > 0) {
      //is like Clone (), allocate array based upon S Ize not capacity
      ensurecapacityinternal (size);

      Object[] A = Elementdata;
      Read in the ' all elements ' proper order.
      for (int i=0; i<size; i++) {
        A[i] = S.readobject ();}}}
  

Code 6

private void WriteObject (Java.io.ObjectOutputStream s)
    throws java.io.ioexception{
    //Write out element count, And any hidden stuff
    int expectedmodcount = Modcount;
    S.defaultwriteobject ();

    Write out size as capacity to behavioural compatibility with clone ()
    s.writeint (size);

    Write out all elements in the proper order.
    for (int i=0; i<size; i++) {
      s.writeobject (elementdata[i]);

    if (Modcount!= expectedmodcount) {
      throw new concurrentmodificationexception ();
    }
  }

So why is ArrayList to serialize in this way?

Why transient

ArrayList is actually a dynamic array that automatically increases the length of the set after it is full, and if the array automatically grows at 100 and only one element is actually placed, the 99 null elements are serialized. To ensure that so much null is not serialized at the same time as serialization, ArrayList sets the element array to transient.

Why WriteObject and ReadObject

As mentioned earlier, to prevent an array containing a large number of empty objects from being serialized, ArrayList uses transient to declare elementdatain order to optimize storage.
However, as a collection, you must also ensure that the elements in the serialization process are persisted, so that the elements are preserved by overriding the WriteObject and ReadObject methods.

The writeobject method saves the elements in the elementdata array to the output stream (ObjectOutputStream).

The readobject method reads the object from the input stream (ObjectInputStream) and saves the assignment to the elementdata array.

So we're going to try to answer the question we just raised:

1. How to customize serialization and deserialization policies

A: You can add writeobject and ReadObject methods to the serialized class. 2, then the question comes again:

Although the WriteObject and ReadObject methods are written in ArrayList, these two methods are not shown to be invoked.

So if a class contains WriteObject and ReadObject methods, how are these two methods invoked?

VI. ObjectOutputStream

From code 4, we can see that the serialization process of an object is accomplished through ObjectOutputStream and objectinputputstream, so with just the question, let's analyze the WriteObject in ArrayList and How exactly is the ReadObject method invoked?

To save space, here's a call stack for ObjectOutputStream's writeobject:

WriteObject---> WRITEOBJECT0--->writeordinaryobject--->writeserialdata--->invokewriteobject

Here's a look at Invokewriteobject:

void Invokewriteobject (Object obj, objectoutputstream out)
    throws IOException, unsupportedoperationexception
  {
    if (Writeobjectmethod!= null) {
      try {
        writeobjectmethod.invoke (obj, new object[]{out});
      catch (InvocationTargetException ex) {
        throwable th = ex.gettargetexception ();
        if (th instanceof IOException) {
          throw (ioexception) th;
        } else {
          throwmiscexception (th);
        }
      } catch (Illegalaccessexception ex) {
        //should not occur, as access checks have been suppressed throw
        new Interna Lerror (ex);
      }
    else {
      throw new unsupportedoperationexception ();
    }
  }

where Writeobjectmethod.invoke (obj, new object[]{Out}) is critical, the Writeobjectmethod method is invoked by reflection. The official explanation for this writeobjectmethod:

Class-defined WriteObject method, or null if none

In our case, this method is the WriteObject method we defined in ArrayList. was invoked by way of reflection.

So we're going to try to answer the question we just raised:

If a class contains WriteObject and ReadObject methods, how are these two methods invoked?

A: When using the ObjectOutputStream WriteObject method and the ObjectInputStream ReadObject method, it is invoked by reflection.

So far, we've covered the serialization of ArrayList. Well, I wonder if anyone has asked such a question:

Serializable is an empty interface, how does it guarantee that only the method that implements the interface can be serialized and deserialized?

Definition of Serializable interface:

Public interface Serializable {
}

The reader can try to remove the inherited serializable code 1, and then execute Codes 2, throwing java.io.NotSerializableException.

In fact, this question is also very good answer, we go back to just objectoutputstream the writeobject call stack:

WriteObject---> WRITEOBJECT0--->writeordinaryobject--->writeserialdata--->invokewriteobject

There is a piece of code in the WriteObject0 method:

if (obj instanceof String) {
        writestring ((String) obj, unshared);
      } else if (Cl.isarray ()) {
        Writearray (obj), DESC, unshared);
      else if (obj instanceof Enum) {
        writeenum (enum<?>) obj, desc, unshared);
      } else if (obj instanceof Serializ Able) {
        writeordinaryobject (obj, desc, unshared);
      } else {
        if (extendeddebuginfo) {
          throw new Notserializableexception (
            cl.getname () + "\ n" + debuginfostack.tostring ());
        } else {
          throw new Notserializableexception (Cl.getname ());
        }
      

When you perform a serialization operation, you determine whether the class to be serialized is an enum, array, and serializable type, and if not, throw the notserializableexception directly.

Summarize

1. If a class wants to be serialized, it needs to implement the serializable interface. Otherwise, the notserializableexception exception is thrown because the type is checked during the serialization operation, requiring the serialized class to belong to any of the enum, array, and serializable types.

2. Add this keyword before the variable declaration to prevent the variable from being serialized to a file.

3. Add WriteObject and ReadObject methods to the class to implement a custom serialization strategy

The above is the entire content of this article, I hope to help you learn.

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.