Java Serialization and persistence

Source: Internet
Author: User
Tags object serialization

 Thread Safety (reproduced) JAVA Reflection Annotation JAVA Persistent Serialization (reprint)

2011-04-19 23:05:30|  Category: JAVA | Tags: serializing person deserialization java FirstName | report | font size big medium small Subscribe

To: This article is a comprehensive introduction of the Java serialization technology in all aspects of knowledge, from the basis of serialization technology,
This paper introduces the mechanism of Java serialization technology and the principle of serialization technology. In the following sections, we discuss in detail the serialized
Advanced topics-How to precisely control the serialization mechanism. By reading this article, you can learn how to use the Java sequence
and correct use of the method to avoid misuse of the technology in actual programming. And to know how to use it efficiently.
The technology to accomplish special functions.

Keywords: serialization (Serialize), deserialization (deserialize), class loading (classload), fingerprint technology
(fingerprint)


1 Overview of the Java serialization technology
The Java serialization technique allows you to write the state of an object into a byte stream, and can be used from somewhere else
Read the data in the byte stream. Reconstructs an identical object. This mechanism allows you to move objects through the network
And can persist objects to databases, files and other systems at any time. The serialization mechanism of Java is RMI,
The technical basis of EJB, Jnni and other technologies.
1.1 Technical Fundamentals of serialization
Not all Java classes can be serialized, in order for the class you specify to be serializable, you must make the class
Implement the following interfaces:
Java.io.Serializable
It is important to note that the interface does not have any methods. Implementing this class is simply a token of your class readiness support sequence
The function of the. Let's look at the following code:
/**
* Abstract basic classes, complete some basic definitions
*/
Public abstract class humanoid
{
protected int noofheads;
private static int totalheads;
Public humanoid ()
{
This (1);
}
Public humanoid (int noofheads)
{
How to properly use the Java Serialization Technology research series
if (Noofheads > 10)
throw new Error ("be serious. More than heads?! ");
This.noofheads = noofheads;
Synchronized (Humanoid.class)
{
Totalheads + = Noofheads;
}
}
public int Getheadcount ()
{
return totalheads;
}
}
A subclass of this class is as follows:
/**
* Humanoid implementation class, implementation of the serialization interface
*/
Import java.io.*;
public class person extends humanoid
Implements Java.io.Serializable
{
Private String LastName;
Private String FirstName;
private transient Thread workerthread;
private static int population;
Public person (string lastName, String firstName)
{
This.lastname = LastName;
This.firstname = FirstName;
Synchronized (Person.class)
{
population++;
}
}
Public String toString ()
{
Return "person" + FirstName + "" + lastName;
}
static synchronized public int getpopulation ()
{
return population;
}
}
1.2 Serialization and deserialization of objects
The class person class above implements the Serializable interface, so it can be serialized. If we're going to put a
Serializable objects can be serialized into a file or database, requiring support for the following classes:
Java.io.ObjectOutputStream
How to properly use the Java Serialization Technology research series
The following code is responsible for completing the serialization of the person class:
/**
* The serialized class of person, which writes the person to the file system through this class.
*/
Import java.io.*;
public class Writeinstance
{
public static void Main (String [] args) throws Exception
{
if (args.length! = 1)
{
System.out.println ("Usage:java writeinstance file");
System.exit (-1);
}
FileOutputStream fos = new FileOutputStream (args[0]);
ObjectOutputStream oos = new ObjectOutputStream (FOS);
Person p = new person ("gaoyanbing", "Haiger");
Oos.writeobject (P);
}
}
If the class that we want to serialize is not actually serializable, the following exception is thrown when it is serialized:
Java.io.NotSerializableException
When we serialize a person into a file, if we need to recover the object from the file,
We need to use the following classes:
Java.io.ObjectInputStream
The code to deserialize the person class from the file is implemented as follows:
/**
* Person's deserialization class, which reads serialized data from the file system and constructs a
* Person object.
*/
Import java.io.*;
public class Readinstance
{
public static void Main (String [] args) throws Exception
{
if (args.length! = 1)
{
System.out.println ("Usage:java readinstance filename");
System.exit (-1);
}
FileInputStream fis = new FileInputStream (args[0]);
ObjectInputStream ois = new ObjectInputStream (FIS);
Object o = Ois.readobject ();
How to properly use the Java Serialization Technology research series
System.out.println ("read object" + O);
}
}
1.3 Serialization of processing principles for classes
Not all of the fields and properties of a class that implements a serialized interface can be serialized. We are divided into the following
Several sections to illustrate:
U if the class has a parent class, consider it in two cases if the parent class already implements a serializable interface. The
The corresponding fields and properties of the parent class are treated the same as the class, if the parent class of the class does not implement Serializable
, all field properties of the parent class of the class will not be serialized.
U if a property of the class is identified as a static type, the property cannot be serialized;
u if an attribute of the class is identified by the transient keyword, the property cannot be serialized;
It is important to note that when we annotate a class that can be serialized, the following properties should be set to transient
To avoid serialization:
U thread-related properties;
u need to access the properties of IO, local resources, network resources, etc.
U does not implement serializable interface properties; (Note: If a property is not serializable, we
If it is not identified with transient, it is thrown when the object is serialized.
Java.io.NotSerializableException exception).
1.4 Constructors and serialization
For the processing of the parent class, if the parent class does not implement a serialization interface, it must have a default constructor (that is, there is no
constructor for the parameter). Why is it so stipulated? Let's look at practical examples. Still using the humanoid above
and the person class. We add the output statements in their constructors:
/**
* Abstract basic classes, complete some basic definitions
*/
Public abstract class humanoid
{
protected int noofheads;
private static int totalheads;
Public humanoid ()
{
This (1);
System.out.println ("Human ' s default constructor is invoked");
}
Public humanoid (int noofheads)
{
if (Noofheads > 10)
throw new Error ("be serious. More than heads?! ");
How to properly use the Java Serialization Technology research series
This.noofheads = noofheads;
Synchronized (Humanoid.class)
{
Totalheads + = Noofheads;
}
}
public int Getheadcount ()
{
return totalheads;
}
}
/**
* Humanoid implementation class, implementation of the serialization interface
*/
Import java.io.*;
public class person extends humanoid
Implements Java.io.Serializable
{
Private String LastName;
Private String FirstName;
private transient Thread workerthread;
private static int population;
Public person (string lastName, String firstName)
{
This.lastname = LastName;
This.firstname = FirstName;
Synchronized (Person.class)
{
population++;
}
SYSTEM.OUT.PRINTLN ("person's constructor is invoked");
}
Public String toString ()
{
Return "person" + FirstName + "" + lastName;
}
static synchronized public int getpopulation ()
{
return population;
}
}
The result of running its serializer and the Deserializer at the command line is:
How to properly use the Java Serialization Technology research series
As you can see, when you construct a person object from a stream, the parent class of the person humanoid the default
The constructor is called. Of course, there's absolutely no need to worry, if you don't give the parent class A default constructor,
You will get an error when translating.
Here, we make the following modifications to the parent class humanoid:
/**
* Abstract basic classes, complete some basic definitions
*/
Public class humanoid implements Java.io.Serializable
{
protected int noofheads;
private static int totalheads;
Public humanoid ()
{
This (1);
System.out.println ("Human ' s default constructor is invoked");
}
Public humanoid (int noofheads)
{
if (Noofheads > 10)
throw new Error ("be serious. More than heads?! ");
This.noofheads = noofheads;
Synchronized (Humanoid.class)
{
Totalheads + = Noofheads;
}
}
public int Getheadcount ()
{
return totalheads;
}
}
We mark the parent class as serializable and then look at the result of the run:
How to properly use the Java Serialization Technology research series
As you can see, when deserializing, if the parent class is also serializable, its default constructor does not
Call. What is this for?
This is because Java obtains its object data from the stream when it deserializes the serialized object into the afterlife
Into an object instance, not through its constructor, after all, our serializable class may have multiple constructs
function, if our serializable class does not have a default constructor, the deserialization mechanism does not know which construct to invoke
The function is correct.
1.5 problems caused by serialization
We can see the above example, in the Person class, whose field population is obviously want to track in a
How many instances of the person class in the JVM, this field is assigned in its constructor, when we are in the same JVM
When serializing a person and deserializing it, because the constructor of the person is not called when deserializing, so
This mechanism does not guarantee the correct acquisition of the number of instances of a person in a JVM, and in the latter part we will detail
Discuss this problem and give a better solution.
2 Control Serialization Technology
2.1 Using the ReadObject and WriteObject methods
Since our serialization of objects is based on the following classes to implement the specific serialization process:
Java.io.ObjectOutputStream
The class is mainly through its WriteObject method to achieve the object serialization process, the class also provides a
Mechanisms to implement user-defined writeobject functions. The method is to implement a in our class that requires serialization.
How to properly use the Java Serialization Technology research series
A writeobject method that will automatically callback the object when it is serialized by ObjectOutputStream.
This completes our custom serialization functionality.
Similarly, the deserialized class implements the same callback mechanism, and we extend its readobject to implement self-
The deserialization mechanism defined.
This flexible callback mechanism solves the problem posed by the above-mentioned serialization,
Problem, we can completely avoid the problem of inaccurate population counting by writing the following ReadObject method:
private void ReadObject (ObjectInputStream ois)
Throws IOException, ClassNotFoundException
{
Ois.defaultreadobject ();
Synchronized (Person.class)
{
population++;
}
System.out.println ("Adjusting population in readobject");
}
2.2 Class versioning for serialization processes
This section discusses the following issues:
U how to find the class of object during object deserialization;
If you serialize and deserialize the classes on both sides are not the same version, how to control;
Searching mechanism of 2.2.1 serialization class
During the deserialization of an object, it is necessary for the class to be deserialized to be found by ClassLoader, otherwise
A Java.lang.ClassNotFoundException exception is thrown during deserialization. About ClassLoader how to
Looking for class, here is not much to say, you can refer to my other article discusses ClassLoader "in the non-management environment
How to implement thermal deployment. We're just concerned about the class that the serialized object corresponds to, which classloader to load
Of To do this, we modify the above
/**
* Modified Deserialization class
*/
Import java.io.*;
public class Readinstance
{
public void Readperson (String filename)
{
How to properly use the Java Serialization Technology research series
try{
FileInputStream fis = new FileInputStream (filename);
ObjectInputStream ois = new ObjectInputStream (FIS);
Object o = Ois.readobject ();
System.out.println ("read object" + O);
System.out.println (This.getclass (). getClassLoader ());
Person person = (person) o;
System.out.println (Person.getclass (). getClassLoader ());
}catch (java.io.IOException IE)
{
Ie.printstacktrace ();
}catch (classnotfoundexception CE)
{
Ce.printstacktrace ();
}
}
public static void Main (String [] args) throws Exception
{
if (args.length! = 1)
{
System.out.println ("Usage:java readinstance filename");
System.exit (-1);
}
Readinstance readinstance = new Readinstance ();
Readinstance.readperson (Args[0]);
}
We look at its classloader primarily through two lines of code with a yellow background, and the results are as follows:
It can be seen that the class loader of the serialization class formally deserializes the class loader that implements the class. In that case, we
You can make it visible by making the version of the most recent person class available to only the classloader of that serializer. and older
Version is not a method that is visible to the ClassLoader to avoid the problem of multiple versions of the classes during deserialization. When
However, we have to do a special discussion on the issue of the version of the class below.
How to properly use the Java Serialization Technology research series
2.2.2 Serialization class multi-version control
If versions of this class are present in the deserialized JVM, how is the deserialization mechanism
What's the reason?
To avoid this problem, the Java serialization mechanism provides a fingerprint technique, with different classes with different versions of the
Fingerprint information, through its fingerprint can be identified in the current JVM is not the class and will be deserialized after the object corresponding
The class is the same version. The thumbprint is implemented as a long type of 64bit. Secure Hash Algorithm (SHA-1)
The basic information of the class to be serialized (including information such as the class name, the editor of the class, the parent interface of the class, and various properties)
The fingerprint of the 64bit. We can print the fingerprint of a serializable class using the command serialver that comes with the JDK.
Information. As follows:
When we have inconsistent versions of the classes on both sides, the deserialization will error:
How to properly use the Java Serialization Technology research series
The solution: from the above output, it can be seen that the fingerprint is provided by the following internal variables:
Private static final long serialversionuid;
If we provide control of this property in the class, we can implement the custom control of the serialized fingerprint of the class. For
In this, we define the variable in the person class:
Private static final long serialversionuid= 6921661392987334380L;
When we modify the person class, we publish different versions of the JVM to the deserialization end, and there is no version conflict.
The problem. It is important to note that the value of the serialversionuid is required to be obtained through the Serialver command. and cannot
Set yourself casually, or there may be a coincidence.
It is important to note that manual setup of Serialversionuid sometimes poses problems such as the possibility that we may
Made a critical change. Causes a substantial incompatibility between the versions of the two classes. To avoid this failure, we need to
Knowing what changes can cause substantial incompatibilities, the table below lists the material incompatibilities and
Minor (compatible) changes:
Change Type Example
Compatible changes
U add attribute (Adding fields)
U Add/Remove Class (Adding/removing classes)
U Add/Remove Writeobject/readobject method (adding/removing
Writeobject/readobject)
U add serialization flag (adding Serializable)
U Change access modifier (changing access modifier)
u delete static/non-serializable properties (removing Static/transient from
A field)
Incompatible changes
U Delete attribute (Deleting fields)
U delete a class in an inheritance or implementation hierarchy (removing classes in a
Hierarchy
U add a static/non-serializable field (adding Static/transient to a
Field
U Modify simple variable type (changing type of a primitive)
U switching between Serializable or externalizable
U delete Serialization flag (removing serializable/externalizable)
U change readobject/writeobject control of the default property value (changing
Whether Readobject/writeobject handles default field
Data
U adding writereplace or readresolve that produces
Objects incompatible with older versions
Also, from the Java serialization specification, it is not pointed out that when we make a substantial incompatibility modification to the class, the reverse order
What the consequences of listing would be. Not all incompatible modifications can cause deserialization failures. For example, if we delete
In addition to an attribute, the deserialization mechanism simply discards the property's data when deserializing. From
JDK reference, we can get some incompatible changes caused by the consequences of the following table:
How to properly use the Java Serialization Technology research series
Deserialization results caused by incompatible modifications
Delete Property
(Deleting a field) silently ignored
Delete a class in an inheritance or implementation hierarchy
(Moving classes in inheritance
Hierarchy
Exception
Add a static/non-serializable property
(Adding static/transient)
Silently ignored
modifying basic property types
(Changing primitive type)
Exception
Changing the use of default property values
(Changing use of default field data)
Exception
Switching between serialized and non-serialized and internal and external classes
(Switching Serializable and
externalizable)
Exception
Remove serializable or Externalizable flag
(Removing Serializable or
externalizable)
Exception
Returns incompatible classes
(Returning incompatible Class)
Depends on incompatibility
2.3 Controlling the serialization process of the properties displayed
In the default Java serialization mechanism, the corresponding mapping of the properties of an object to a byte stream is self-
It is done in a dynamic and transparent manner. At serialization time, the name of the object's property is defaulted as the name in the byte stream. When the
When an object is deserialized, it is mapped to the properties of the newly generated object according to the name in the byte stream.
For instance. When one of our person objects is serialized, a property of person FirstName
is the default name for this property in the byte stream. When the person object is deserialized, the serialization mechanism
The value of the FirstName obtained in the stream is assigned to the attribute named FirstName in the new person instance.
The Java serialization mechanism provides the relevant hook functions for us to use, through which we can precisely
Control of the serialization and deserialization process described above. ObjectInputStream's inner class GetField provides a set of properties
Data is removed from the stream, while ObjectOutputStream's inner class Putfield provides the attribute data
Control mechanisms in the inflow. In terms of objectinputstream, we need to complete the flow in the ReadObject method.
Read the corresponding property data. For example, we now update the version of the Person class from table one below to table two:
/**
* Before modifying the old version of the person class, in order to simplify, we removed all irrelevant code
*/
Import java.io.*;
public class person extends humanoid
Implements Java.io.Serializable
{
Private String LastName;
How to properly use the Java Serialization Technology research series
Private String FirstName;
Private static final long serialversionuid =6921661392987334380l;
Private person ()
{
}
Public person (string lastName, String firstName)
{
This.lastname = LastName;
This.firstname = FirstName;
}
Public String toString ()
{
Return "person" + FirstName + "" + lastName;
}
}
The modified person is:
/**
* Modified Person class, we will FirstName and LastName into the FullName
*/
Import java.io.*;
public class person extends humanoid
Implements Java.io.Serializable
{
Private String FullName;
Private static final long serialversionuid =6921661392987334380l;
Private person ()
{
}
Public person (String FullName)
{
This.lastname = FullName;
}
Public String toString ()
{
Return "person" + fullName;
}
}
To do this, we need to write the ReadObject method for the person class as follows:
private void ReadObject (ObjectInputStream ois)
Throws Ioexception,classnotfoundexception
{
Objectinputstream.getfield GF = Ois.readfields ();
FullName = (String) gf.get ("FullName", null);
if (FullName = = null)
{
String lastName = (string) gf.get ("LastName", null);
How to properly use the Java Serialization Technology research series
String firstName = (string) gf.get ("FirstName", null);
if ((LastName = = null) | | (FirstName = = null))
{
throw new Invalidclassexception ("Invalid person");
}
FullName = FirstName + "" + lastName;
}
}
Our order of execution is:
1) Compile the old person and all classes;
2) serialize the old person to the file;
3) Change to the new version of the person class;
4) Compile the new person class;
5) deserialization of person;
The result was very smooth, and the modified deserialization mechanism still correctly fetched the old version of the person from the stream.
Property information and finishes assigning a value to the new version of the person's property.
There are two points to note when using ObjectInputStream's readobject to handle deserialization properties:
Once you use the deserialization of your own control property, you must complete the deserialization of all the properties (that is, to give all
attribute Assignment);
You need to be aware when using the GET method of the inner class GetField, if get is a neither in the old version
This occurs when there are no properties that appear in the new version, the method throws an exception:
Illegalargumentexception:no Such field, so we should be in a try block
To use this method.
Similarly, we can control the serialization of object properties through the WriteObject method. This is no longer a
For example, if you are interested, you can implement the WriteObject method of the person class yourself, and use
ObjectOutputStream internal class Putfield to complete the manual serialization of the property.
3 Summary
The Java serialization mechanism provides a powerful processing power. In general, in order to maximize the use of Java-provided automation
Mechanism, we do not need to do any interference with the serialization process. But at some point we need to implement some special
Functions, such as multi-version control of classes, serialization control of special fields, etc. There are many ways to achieve this
Some features:
U use the serialization mechanism to provide the hook functions readobject and writeobject;
U overwrite the metadata information of the serialized class;
How to properly use the Java Serialization Technology research series
U enables the class to implement the Externalizable interface instead of implementing the Serializable interface.

Java Serialization and persistence

Related Article

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.