Java Object Serialization

1 Java对象序列化?

是把对象图转换成字节数组、把字节数组转换成等价对象图的过程。

序列化是在组件间传输对象的通用有效的协议。

2 Java序列化算法

  1. 输出和实例关联的类元数据信息。
  2. 递归地输出父类描述信息直到找到java.lang.Object。
  3. 从最高层父类开始递归输出实例数据值。

2.1 Java序列化:循环引用(Cycle Reference)问题?

Within a stream, the first reference to any object results in the object being serialized or externalized and the assignment of a handle for that object. Subsequent references to that object are encoded as the handle. Using object handles preserves sharing and circular references that occur naturally in object graphs. Subsequent references to an object use only the handle allowing a very compact representation.

In other words it checks a IdentityHashMap for each object it writes out. and if present will just write out the handle.

3 默认序列化机制

如果仅仅只是让某个类实现Serializable接口,而没有其它任何处理的话,则就是使用默认序列化机制。使用默认机制,在序列化对象时,不仅会序列化当前对象本身,还会对该对象引用的其它对象也进行序列化,同样地,这些其它对象引用的另外对象也将被序列化,以此类推。所以,如果一个对象包含的成员变量是容器类对象,而这些容器所含有的元素也是容器类对象,那么这个序列化的过程就会较复杂,开销也较大。

4 定制序列化机制(custom serialized form)

通过使用Java序列化机制的内置特性,可以通过在可序列化的类中提供下面两个方法定制Java序列化:

  • private void writeObject(ObjectOutputStream out) throws IOException;
  • private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException;

注意:上面两个方法必须是private。

public class Person implements Serializable {
    String firstName, lastName;
    private transient int age;
    Address address;

    public Person(String firstName, String lastName, Address address,int age) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.address = address;
        this.age = age;
    }

    private void writeObject(ObjectOutputStream out) throws IOException {
        out.defaultWriteObject();
        out.writeInt(age);
    }

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException{
        in.defaultReadObject();
        age = in.readInt();
    }
}

调用顺序:ObjectOutputStream.writeObject--->Person.writeObject;

ObjectInputStream.readObject--->Person.readObject

5 Externalizable接口

public class Person implements Externalizable {
    String firstName, lastName;
    private transient int age;
    Address address;
    public Person(String firstName, String lastName, Address address,int age) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.address = address;
        this.age = age;
    }

    public Person() {
        System.out.println("none-arg constructor");
    }

    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeObject(firstName);
        out.writeObject(lastName);
        out.writeObject(address);
        out.writeInt(age);
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        firstName = (String)in.readObject();
        lastName = (String)in.readObject();
        address = (Address)in.readObject();
        age = in.readInt();
    }
}

6 用readResolve进行实例控制

public class SerializedSingleton implements Serializable {
    private static final long serialVersionUID = -7604766932017737115L;

    private SerializedSingleton(){}

    private static class SingletonHelper{
        private static final SerializedSingleton instance = new SerializedSingleton();
    }

    public static SerializedSingleton getInstance(){
        return SingletonHelper.instance;
    }

    protected Object readResolve() {
        return getInstance();
    }
 }

如果是Singleton,JDK5以后最好用Enum实现。

References

  1. Java Object Serialization Specification
  2. The Java serialization algorithm revealed
  3. 理解Java对象序列化

results matching ""

    No results matching ""