`

序列化和性能(转)

    博客分类:
  • java
 
阅读更多

转自:http://www.360doc.com/content/06/1217/00/15643_296709.shtml

 

通常人们认识的序列化类实现java.io.Serializable 像这样:


 

import java.io.*; 
public class Pojo implements Serializable { 
	private static final long serialVersionUID = L; 
	.... 
}
 

 

 

这种做法被广大程序员广泛应用,然而这种序列化的性能很低。它使用反射机制寻找序列化类的类变量和这些类变量的类型。大家都知道反射是一个非常消耗时间的处理过程。

我们如何能尽可能的在程序中减轻这种负载呢?有下面三种方法:

1.使用ObjectStreamField类

2.使用readObject / writeObject 方法

3.使用Externalizable 接口

在上面的方法中,性能最好的是使用Externalizable 接口。为了便于理解,将为不同的方法例举一个例子。

ObjectStreamField 类为序列化机制提供序列化对象的成员变量以及成员变量的类型。这样做的好是可以节约一部分时间,他不必通过反射机制去查询成员变量以及类型。关键字transient 仍然可以在这种方式下正常使用,不过在创建ObjectStreamField对象添加序列话成员变量的时候,剔除transient 标识的成员变量。

 

public class Pojo implements Serializable { 
private static final long serialVersionUID = 1L; 
private String valueA = "SomeTextA"; 
private int valueB = 10; 
private float valueC = 100f; 
private double valueD = 100.100d; 
private short valueE = 10; 
// Getters and setters go here. 
private static final ObjectStreamField[] serialPersistFields = { 
new ObjectStreamField("valueA", String.class), 
new ObjectStreamField("valueB", Integer.class), 
new ObjectStreamField("valueC", Float.class), 
new ObjectStreamField("valueD", Double.class), 
new ObjectStreamField("valueE", Short.class) 
}; 
} 
 

 

就像你所看到的,为了提升性能得必须指明你所序列化的成员变量,当然除了transient 的成员变量。

第二种方法是使用readObject / writeObject 方法。

 

public class Pojo implements Serializable { 
private static final long serialVersionUID = 1L; 
private String valueA = "SomeTextA"; 
private int valueB = 10; 
private float valueC = 100f; 
private double valueD = 100.100d; 
private short valueE = 10; 
// Getters and setters go here. 
private void writeObject(ObjectOutputStream oos) throws IOException { 
oos.writeUTF(valueA); 
oos.writeInt(valueB); 
oos.writeFloat(valueC); 
oos.writeDouble(valueD); 
oos.writeShort(valueE); 
} 
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { 
this.valueA = ois.readUTF(); 
this.valueB = ois.readInt(); 
this.valueC = ois.readFloat(); 
this.valueD= ois.readDouble(); 
this.valueE= ois.readShort(); 
} 
} 
 

 

这种方式包括了序列化的序列化和反序列化过程。就像上面所展示的,仍然需要声明Serializable 接口。

第三种方式使用Externalizable 接口。

 

public class Pojo implements Externalizable { 
private static final long serialVersionUID = 1L; 
private String valueA = "SomeTextA"; 
private int valueB = 10; 
private float valueC = 100f; 
private double valueD = 100.100d; 
private short valueE = 10; 
// Getters and setters go here. 
public void writeExternal(ObjectOutput out) throws IOException { 
out.writeUTF(valueA); 
out.writeInt(valueB); 
out.writeFloat(valueC); 
out.writeDouble(valueD); 
out.writeShort(valueE); 
} 
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { 
this.valueA = in.readUTF(); 
this.valueB = in.readInt(); 
this.valueC = in.readFloat(); 
this.valueD= in.readDouble(); 
this.valueE= in.readShort(); 
} 
} 
 

 

 

这种方式与readObject / writeObject 方式不同的是不再需要声明Serializable 接口, readObject / writeObject 方法使用ObjectOutput/ObjectInput 接口作为参数代理输入流输出流实现类,并且serialVersionUID 仍然可以使用。

下面将测试各种序列化方法所消耗的时间:

 

public class Run { 
private static int TIMES = 500000; 
public static void main(String[] args) { 
Pojo sp = new Pojo(); 
long start = System.currentTimeMillis(); 
for (int i = 0; i<TIMES;i++){
serialize(sp); 
} 
long duration = System.currentTimeMillis() - start; 
System.out.println("Externalizable: " + duration + "ms."); 
} 
public static void serialize(Pojo o) { 
try { 
ByteArrayOutputStream bout = new ByteArrayOutputStream(); 
ObjectOutputStream out = new ObjectOutputStream(bout); 
out.writeObject(o); 
out.close(); 
} catch (Exception e) { 
e.printStackTrace(); 
} 
} 
} 
 

 

为了获得正确的测试结果,我们制定以下规则 。首先,不能测试一小部分对象,应该取较大的均值。第二,减小不必要的负载。如果测试程序快速产生大量的对象,会产生大量的垃圾收集。

在上面的代码中,我们仅序列化了50000个对象。并且没有将序列化的内容写入磁盘或者网络,因为会产生我们不希望的负载。

还有一点值得注意的是,如果有多个String类型的成员变量,他们之应该是不同的值。如果他们的值相同,那么他们引用的是同一个对象。

下面是不同jdk版本间的测试结果:

JDK 1.4.2_12 

Serializable: 9766ms. 

Streamfield: 9656ms. 

Read/Write object: 7781ms. 

Externalizable: 5875ms. 

 

JDK 1.5.0_19 

Serializable: 9016ms. 

Streamfield: 8859ms. 

Read/Write object: 7141ms. 

Externalizable: 5610ms. 

JDK 1.6.0 (B103) 

Serializable: 7484ms. 

Streamfield: 7312ms. 

Read/Write object: 5610ms. 

Externalizable: 4828ms. 

有趣的是你可以发现使用Externalizable 接口提升了55%的性能。同时也可以看出jdk不同版本的垃圾收集器&Hotpot引擎性能也在提升!


 

 

分享到:
评论

相关推荐

    序列化和反序列化dll文件和proto

    在实际应用中,DLL文件的序列化和反序列化可能会遇到一些挑战,例如版本兼容性、数据安全性和性能优化。而Proto的优势在于其紧凑的二进制格式和跨语言支持,使得它成为网络通信和数据存储的理想选择,特别是在大数据...

    java序列化和反序列化的方法

    * 序列化和反序列化过程中可能会出现性能问题 * 序列化和反序列化过程中可能会出现安全问题 Java 序列化和反序列化是 Java 语言中的一种重要机制,用于将对象转换为字节流,以便在网络上传输或存储。开发者需要根据...

    hessian学习基础篇——序列化和反序列化

    在IT领域,序列化和反序列化是两个关键的概念,特别是在网络通信、数据持久化以及对象存储中。本文将深入探讨Hessian框架的基础知识,它是一个高效的二进制序列化协议,广泛应用于Java和.NET之间跨语言通信。通过...

    C++ JSON 序列化与反序列化

    1. 复杂类型的处理:除了基本类型外,还可以序列化和反序列化自定义类、结构体以及容器(如vector、map等)。对于自定义类型,通常需要重载`operator和`operator>>`,或者使用nlohmann/json库中的`to_json`和`from_...

    学生管理系统(序列化和反序列化)

    5. **性能和效率**:虽然序列化和反序列化提供了方便的数据持久化方式,但需要注意的是,这个过程可能会消耗一定的时间和资源。优化序列化算法和存储格式,比如使用高效的序列化库,可以提高系统的性能。 6. **安全...

    protobuf序列化和反序列化技术

    protobuf序列化和反序列化技术是大数据处理领域中不可或缺的一部分,尤其在实时大数据场景下,高效的数据传输和存储对性能有着直接影响。谷歌推出的Protocol Buffers(简称protobuf)是一种语言无关、平台无关的数据...

    C# 各种序列化和反序列化

    在编程世界中,序列化和反序列化是两个至关重要的概念,尤其是在C#这样的面向对象的语言中。...二进制序列化则在对性能有严格要求且不涉及跨平台的情况下较为合适。开发者应根据具体需求选择合适的序列化策略。

    Jedis序列化和反序列化使用jar

    2. commons-lang3-3.3.2.jar:Apache Commons Lang库提供了许多实用的Java语言功能,包括序列化和反序列化的辅助工具,如`SerializationUtils`类,可用于简化对象的序列化和反序列化操作。 3. commons-beanutils-...

    java序列化和反序列化

    ### Java序列化与反序列化详解 #### 一、Java序列化概述 Java序列化(Serialization...综上所述,Java序列化提供了一种简单有效的方式来处理对象的持久化和传输需求,但开发者也需要考虑其可能带来的性能和安全问题。

    二进制序列化和XML序列化

    在编程领域,序列化是一个重要的...总的来说,选择二进制序列化还是XML序列化取决于应用场景的需求,如数据交换的格式要求、存储空间和性能等因素。在实际开发中,需要根据具体情况权衡利弊,选择最合适的序列化方式。

    Bboss和xstream序列化反序列化性能对比1

    在本文中,我们将深入探讨Bboss和Xstream两个序列化和反序列化库在性能方面的差异。这两个库在Java开发中广泛用于将对象转换为XML格式,以便于存储、传输或持久化。以下是对这两个库的详细分析。 首先,Bboss和...

    .net 序列化和反序列化 Json

    .NET框架中的序列化和反...总之,理解和掌握.NET中的JSON序列化和反序列化是开发Web服务和客户端应用的关键技能,无论选择使用内置方法还是第三方库如Json.NET,都需要根据项目需求来权衡性能、功能和依赖管理等因素。

    C#序列化和反序列化

    在C#编程中,序列化和反序列化是两个关键的概念,它们对于数据存储、网络传输和持久化具有重要作用。...通过深入理解这些概念和实践,开发者可以更好地处理数据的保存和传输,提升应用程序的性能和功能。

    jackson json序列化,反序列化所需jar包

    总的来说,Jackson是一个强大且灵活的JSON处理工具,它的高效性能和易用性使得它在Java开发者中非常受欢迎。通过正确配置和使用这三个jar包,你可以轻松地在Java应用中实现JSON的序列化和反序列化。

    C#的控件使用:树形图TreeView如何实现序列化和反序列化.rar

    此外,为了提高性能和用户体验,可以在用户修改`TreeView`时动态更新序列化的数据,而不是等到程序关闭时一次性序列化整个树。 总之,通过以上步骤,我们可以有效地实现`TreeView`控件的序列化和反序列化,使得应用...

    java原生序列化和Kryo序列化性能实例对比分析

    "java原生序列化和Kryo序列化性能实例对比分析" 本文主要介绍了java原生序列化和Kryo序列化性能实例对比分析,涉及Java和kryo序列化和反序列化相关实例。下面是对标题、描述、标签和部分内容的详细说明: 1. 序列...

    Unity 中使用Protobuf进行序列化和反序列化的Demo

    在Unity游戏引擎中,开发人员经常需要处理数据的序列化和反序列化,以便于存储、传输或网络通信。Protocol Buffers(Protobuf)是一种高效、跨平台的数据序列化协议,由Google开发。本Demo将展示如何在Unity中集成并...

    序列化反序列化例题net

    在.NET框架中,序列化和反序列化是两个重要的概念,它们主要用于数据持久化、网络传输和跨进程通信。理解并熟练运用这些技术对于任何.NET开发者来说都是至关重要的。 序列化是将对象的状态(包括其属性和字段)转换...

    序列化和反序列化doc文档.rar

    1. **效率**:序列化和反序列化的速度对性能有很大影响,尤其是在大数据量和高并发的场景下。 2. **兼容性**:序列化格式应具有良好的跨平台和跨语言兼容性,以便不同系统间能互相交换数据。 3. **安全性**:序列化...

Global site tag (gtag.js) - Google Analytics