Java序列化是指把Java对象保存为二进制字节码的过程,Java反序列化是指把二进制码重新转换成Java对象的过程。
那么为什么需要序列化呢?
- 一般情况下Java对象的声明周期都比Java虚拟机的要短,实际应用中我们希望在JVM停止运行之后能够持久化指定的对象,这时候就需要把对象进行序列化之后保存。
- 需要把Java对象通过网络进行传输的时候。因为数据只能够以二进制的形式在网络中进行传输,因此当把对象通过网络发送出去之前需要先序列化成二进制数据,在接收端读到二进制数据之后反序列化成Java对象。
Serializable
接口仅用于标识可序列化的语义
package java.io;
/**
* Serializability of a class is enabled by the class implementing the
* java.io.Serializable interface. Classes that do not implement this
* interface will not have any of their state serialized or
* deserialized. All subtypes of a serializable class are themselves
* serializable. The serialization interface has no methods or fields
* and serves only to identify the semantics of being serializable. <p>
*
* To allow subtypes of non-serializable classes to be serialized, the
* subtype may assume responsibility for saving and restoring the
* state of the supertype's public, protected, and (if accessible)
* package fields. The subtype may assume this responsibility only if
* the class it extends has an accessible no-arg constructor to
* initialize the class's state. It is an error to declare a class
* Serializable if this is not the case. The error will be detected at
* runtime. <p>
*
* During deserialization, the fields of non-serializable classes will
* be initialized using the public or protected no-arg constructor of
* the class. A no-arg constructor must be accessible to the subclass
* that is serializable. The fields of serializable subclasses will
* be restored from the stream. <p>
*
* When traversing a graph, an object may be encountered that does not
* support the Serializable interface. In this case the
* NotSerializableException will be thrown and will identify the class
* of the non-serializable object. <p>
*
* Classes that require special handling during the serialization and
* deserialization process must implement special methods with these exact
* signatures:
*
* <PRE>
* private void writeObject(java.io.ObjectOutputStream out)
* throws IOException
* private void readObject(java.io.ObjectInputStream in)
* throws IOException, ClassNotFoundException;
* private void readObjectNoData()
* throws ObjectStreamException;
* </PRE>
*
* <p>The writeObject method is responsible for writing the state of the
* object for its particular class so that the corresponding
* readObject method can restore it. The default mechanism for saving
* the Object's fields can be invoked by calling
* out.defaultWriteObject. The method does not need to concern
* itself with the state belonging to its superclasses or subclasses.
* State is saved by writing the individual fields to the
* ObjectOutputStream using the writeObject method or by using the
* methods for primitive data types supported by DataOutput.
*
* <p>The readObject method is responsible for reading from the stream and
* restoring the classes fields. It may call in.defaultReadObject to invoke
* the default mechanism for restoring the object's non-static and
* non-transient fields. The defaultReadObject method uses information in
* the stream to assign the fields of the object saved in the stream with the
* correspondingly named fields in the current object. This handles the case
* when the class has evolved to add new fields. The method does not need to
* concern itself with the state belonging to its superclasses or subclasses.
* State is saved by writing the individual fields to the
* ObjectOutputStream using the writeObject method or by using the
* methods for primitive data types supported by DataOutput.
*
* <p>The readObjectNoData method is responsible for initializing the state of
* the object for its particular class in the event that the serialization
* stream does not list the given class as a superclass of the object being
* deserialized. This may occur in cases where the receiving party uses a
* different version of the deserialized instance's class than the sending
* party, and the receiver's version extends classes that are not extended by
* the sender's version. This may also occur if the serialization stream has
* been tampered; hence, readObjectNoData is useful for initializing
* deserialized objects properly despite a "hostile" or incomplete source
* stream.
*
* <p>Serializable classes that need to designate an alternative object to be
* used when writing an object to the stream should implement this
* special method with the exact signature:
*
* <PRE>
* ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException;
* </PRE><p>
*
* This writeReplace method is invoked by serialization if the method
* exists and it would be accessible from a method defined within the
* class of the object being serialized. Thus, the method can have private,
* protected and package-private access. Subclass access to this method
* follows java accessibility rules. <p>
*
* Classes that need to designate a replacement when an instance of it
* is read from the stream should implement this special method with the
* exact signature.
*
* <PRE>
* ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException;
* </PRE><p>
*
* This readResolve method follows the same invocation rules and
* accessibility rules as writeReplace.<p>
*
* The serialization runtime associates with each serializable class a version
* number, called a serialVersionUID, which is used during deserialization to
* verify that the sender and receiver of a serialized object have loaded
* classes for that object that are compatible with respect to serialization.
* If the receiver has loaded a class for the object that has a different
* serialVersionUID than that of the corresponding sender's class, then
* deserialization will result in an {@link InvalidClassException}. A
* serializable class can declare its own serialVersionUID explicitly by
* declaring a field named <code>"serialVersionUID"</code> that must be static,
* final, and of type <code>long</code>:
*
* <PRE>
* ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;
* </PRE>
*
* If a serializable class does not explicitly declare a serialVersionUID, then
* the serialization runtime will calculate a default serialVersionUID value
* for that class based on various aspects of the class, as described in the
* Java(TM) Object Serialization Specification. However, it is <em>strongly
* recommended</em> that all serializable classes explicitly declare
* serialVersionUID values, since the default serialVersionUID computation is
* highly sensitive to class details that may vary depending on compiler
* implementations, and can thus result in unexpected
* <code>InvalidClassException</code>s during deserialization. Therefore, to
* guarantee a consistent serialVersionUID value across different java compiler
* implementations, a serializable class must declare an explicit
* serialVersionUID value. It is also strongly advised that explicit
* serialVersionUID declarations use the <code>private</code> modifier where
* possible, since such declarations apply only to the immediately declaring
* class--serialVersionUID fields are not useful as inherited members. Array
* classes cannot declare an explicit serialVersionUID, so they always have
* the default computed value, but the requirement for matching
* serialVersionUID values is waived for array classes.
*
* @author unascribed
* @see java.io.ObjectOutputStream
* @see java.io.ObjectInputStream
* @see java.io.ObjectOutput
* @see java.io.ObjectInput
* @see java.io.Externalizable
* @since JDK1.1
*/
public interface Serializable {
}
ObjectInputStream
继承InputStream
抽象类并实现 ObjectInput
和ObjectStreamConstants
接口
package java.io;
import java.io.ObjectStreamClass.WeakClassKey;
import java.lang.ref.ReferenceQueue;
import java.lang.reflect.Array;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import static java.io.ObjectStreamClass.processQueue;
import sun.misc.SharedSecrets;
import sun.misc.ObjectInputFilter;
import sun.misc.ObjectStreamClassValidator;
import sun.misc.SharedSecrets;
import sun.reflect.misc.ReflectUtil;
import sun.misc.JavaOISAccess;
import sun.util.logging.PlatformLogger;
/**
* An ObjectInputStream deserializes primitive data and objects previously
* written using an ObjectOutputStream.
*
* <p>ObjectOutputStream and ObjectInputStream can provide an application with
* persistent storage for graphs of objects when used with a FileOutputStream
* and FileInputStream respectively. ObjectInputStream is used to recover
* those objects previously serialized. Other uses include passing objects
* between hosts using a socket stream or for marshaling and unmarshaling
* arguments and parameters in a remote communication system.
*
* <p>ObjectInputStream ensures that the types of all objects in the graph
* created from the stream match the classes present in the Java Virtual
* Machine. Classes are loaded as required using the standard mechanisms.
*
* <p>Only objects that support the java.io.Serializable or
* java.io.Externalizable interface can be read from streams.
*
* <p>The method <code>readObject</code> is used to read an object from the
* stream. Java's safe casting should be used to get the desired type. In
* Java, strings and arrays are objects and are treated as objects during
* serialization. When read they need to be cast to the expected type.
*
* <p>Primitive data types can be read from the stream using the appropriate
* method on DataInput.
*
* <p>The default deserialization mechanism for objects restores the contents
* of each field to the value and type it had when it was written. Fields
* declared as transient or static are ignored by the deserialization process.
* References to other objects cause those objects to be read from the stream
* as necessary. Graphs of objects are restored correctly using a reference
* sharing mechanism. New objects are always allocated when deserializing,
* which prevents existing objects from being overwritten.
*
* <p>Reading an object is analogous to running the constructors of a new
* object. Memory is allocated for the object and initialized to zero (NULL).
* No-arg constructors are invoked for the non-serializable classes and then
* the fields of the serializable classes are restored from the stream starting
* with the serializable class closest to java.lang.object and finishing with
* the object's most specific class.
*
* <p>For example to read from a stream as written by the example in
* ObjectOutputStream:
* <br>
* <pre>
* FileInputStream fis = new FileInputStream("t.tmp");
* ObjectInputStream ois = new ObjectInputStream(fis);
*
* int i = ois.readInt();
* String today = (String) ois.readObject();
* Date date = (Date) ois.readObject();
*
* ois.close();
* </pre>
*
* <p>Classes control how they are serialized by implementing either the
* java.io.Serializable or java.io.Externalizable interfaces.
*
* <p>Implementing the Serializable interface allows object serialization to
* save and restore the entire state of the object and it allows classes to
* evolve between the time the stream is written and the time it is read. It
* automatically traverses references between objects, saving and restoring
* entire graphs.
*
* <p>Serializable classes that require special handling during the
* serialization and deserialization process should implement the following
* methods:
*
* <pre>
* private void writeObject(java.io.ObjectOutputStream stream)
* throws IOException;
* private void readObject(java.io.ObjectInputStream stream)
* throws IOException, ClassNotFoundException;
* private void readObjectNoData()
* throws ObjectStreamException;
* </pre>
*
* <p>The readObject method is responsible for reading and restoring the state
* of the object for its particular class using data written to the stream by
* the corresponding writeObject method. The method does not need to concern
* itself with the state belonging to its superclasses or subclasses. State is
* restored by reading data from the ObjectInputStream for the individual
* fields and making assignments to the appropriate fields of the object.
* Reading primitive data types is supported by DataInput.
*
* <p>Any attempt to read object data which exceeds the boundaries of the
* custom data written by the corresponding writeObject method will cause an
* OptionalDataException to be thrown with an eof field value of true.
* Non-object reads which exceed the end of the allotted data will reflect the
* end of data in the same way that they would indicate the end of the stream:
* bytewise reads will return -1 as the byte read or number of bytes read, and
* primitive reads will throw EOFExceptions. If there is no corresponding
* writeObject method, then the end of default serialized data marks the end of
* the allotted data.
*
* <p>Primitive and object read calls issued from within a readExternal method
* behave in the same manner--if the stream is already positioned at the end of
* data written by the corresponding writeExternal method, object reads will
* throw OptionalDataExceptions with eof set to true, bytewise reads will
* return -1, and primitive reads will throw EOFExceptions. Note that this
* behavior does not hold for streams written with the old
* <code>ObjectStreamConstants.PROTOCOL_VERSION_1</code> protocol, in which the
* end of data written by writeExternal methods is not demarcated, and hence
* cannot be detected.
*
* <p>The readObjectNoData method is responsible for initializing the state of
* the object for its particular class in the event that the serialization
* stream does not list the given class as a superclass of the object being
* deserialized. This may occur in cases where the receiving party uses a
* different version of the deserialized instance's class than the sending
* party, and the receiver's version extends classes that are not extended by
* the sender's version. This may also occur if the serialization stream has
* been tampered; hence, readObjectNoData is useful for initializing
* deserialized objects properly despite a "hostile" or incomplete source
* stream.
*
* <p>Serialization does not read or assign values to the fields of any object
* that does not implement the java.io.Serializable interface. Subclasses of
* Objects that are not serializable can be serializable. In this case the
* non-serializable class must have a no-arg constructor to allow its fields to
* be initialized. In this case it is the responsibility of the subclass to
* save and restore the state of the non-serializable class. It is frequently
* the case that the fields of that class are accessible (public, package, or
* protected) or that there are get and set methods that can be used to restore
* the state.
*
* <p>Any exception that occurs while deserializing an object will be caught by
* the ObjectInputStream and abort the reading process.
*
* <p>Implementing the Externalizable interface allows the object to assume
* complete control over the contents and format of the object's serialized
* form. The methods of the Externalizable interface, writeExternal and
* readExternal, are called to save and restore the objects state. When
* implemented by a class they can write and read their own state using all of
* the methods of ObjectOutput and ObjectInput. It is the responsibility of
* the objects to handle any versioning that occurs.
*
* <p>Enum constants are deserialized differently than ordinary serializable or
* externalizable objects. The serialized form of an enum constant consists
* solely of its name; field values of the constant are not transmitted. To
* deserialize an enum constant, ObjectInputStream reads the constant name from
* the stream; the deserialized constant is then obtained by calling the static
* method <code>Enum.valueOf(Class, String)</code> with the enum constant's
* base type and the received constant name as arguments. Like other
* serializable or externalizable objects, enum constants can function as the
* targets of back references appearing subsequently in the serialization
* stream. The process by which enum constants are deserialized cannot be
* customized: any class-specific readObject, readObjectNoData, and readResolve
* methods defined by enum types are ignored during deserialization.
* Similarly, any serialPersistentFields or serialVersionUID field declarations
* are also ignored--all enum types have a fixed serialVersionUID of 0L.
*
* @author Mike Warres
* @author Roger Riggs
* @see java.io.DataInput
* @see java.io.ObjectOutputStream
* @see java.io.Serializable
* @see <a href="../../../platform/serialization/spec/input.html"> Object Serialization Specification, Section 3, Object Input Classes</a>
* @since JDK1.1
*/