通常人们认识的序列化类实现java.io.Serializable 像这样:
public class Pojo implements Serializable { private static final long serialVersionUID = L; .... } 这种做法被广大程序员广泛应用,然而这种序列化的性能很低。它使用反射机制寻找序列化类的类变量和这些类变量的类型。大家都知道反射是一个非常消耗时间的处理过程。 我们如何能尽可能的在程序中减轻这种负载呢?有下面三种方法: 1.使用ObjectStreamField类 在上面的方法中,性能最好的是使用Externalizable 接口。为了便于理解,将为不同的方法例举一个例子。 ObjectStreamField 类为序列化机制提供序列化对象的成员变量以及成员变量的类型。这样做的好是可以节约一部分时间,他不必通过反射机制去查询成员变量以及类型。关键字transient 仍然可以在这种方式下正常使用,不过在创建ObjectStreamField对象添加序列话成员变量的时候,剔除transient 标识的成员变量。 public class Pojo implements Serializable { private static final long serialVersionUID = 1L; private String valueA = "SomeTextA"; // Getters and setters go here. private static final ObjectStreamField[] serialPersistFields = { 就像你所看到的,为了提升性能得必须指明你所序列化的成员变量,当然除了transient 的成员变量。 第二种方法是使用readObject / writeObject 方法。 public class Pojo implements Serializable { private static final long serialVersionUID = 1L; private String valueA = "SomeTextA"; // Getters and setters go here. private void writeObject(ObjectOutputStream oos) throws IOException { private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
第三种方式使用Externalizable 接口。 public class Pojo implements Externalizable { private static final long serialVersionUID = 1L; private String valueA = "SomeTextA"; // Getters and setters go here. public void writeExternal(ObjectOutput out) throws IOException { public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
下面将测试各种序列化方法所消耗的时间: public class Run { private static int TIMES = 500000; public static void main(String[] args) { long start = System.currentTimeMillis(); System.out.println("Externalizable: " + duration + "ms."); public static void serialize(Pojo o) { }
在上面的代码中,我们仅序列化了50000个对象。并且没有将序列化的内容写入磁盘或者网络,因为会产生我们不希望的负载。 还有一点值得注意的是,如果有多个String类型的成员变量,他们之应该是不同的值。如果他们的值相同,那么他们引用的是同一个对象。 下面是不同jdk版本间的测试结果: JDK 1.4.2_12 Serializable: 9766ms.
Serializable: 9016ms. JDK 1.6.0 (B103) Serializable: 7484ms. 有趣的是你可以发现使用Externalizable 接口提升了55%的性能。同时也可以看出jdk不同版本的垃圾收集器&Hotpot引擎性能也在提升! |
|