java序列化/反序列化之xml、protobuf、protostuff 的比较与使用例子

目录

1、背景

2、测试

  2.1、环境

  2.2、工具

  2.3、说明

  2.4、结果

  2.5、结论

3、xml简单教程

  3.1、准备

  3.2、代码 

4、protobuf简单教程

  4.1、快速入门

    1、下载.exe编译器

    2、编写.proto文件

    3、利用编译器编译.proto文件生成javabean

    4、引用jar包

    5、直接使用javabean自带的序列化、反序列化、提取属性等方法

5、protostuff简单教程

  5.1、快速入门

    1、引用jar包

    2、直接使用相关序列化、反序列化语法

1、背景

  项目中http通信离不开对象的序列化和反序列化,以前框架使用的是xml,通用、可读性强,对于对速度要求不高的系统来说,的确是一种不错的选择。然而最近的一个需求需要使用protobuf,因为其速度比xml快非常多,而业界说到java的序列化和反序列化,更离不开基于protobuf的protostuff,所以针对这三种技术,做了以下简单不专业的比较和介绍。如果大家觉得proto系列还可以的话,或者在以后的项目中,可以考虑使用。

2、测试

2.1 测试环境

xstraem版本:1.3.1

protobuf-java版本:3.0.0-alpha-2

java版本:1.7

-Xms2048m

-Xmx2048m

2.2 测试工具

用时: 控制台输出时间

CPU&内存: jconsole

文件大小: 文件属性

2.3 说明

测试中,xml和protoBuf和protostuff三种测试所使用的JavaBean所拥有的字段类型相同、字段数量相同(约28个)、字段所附的值相同、都包含有一个List<String>字段,用List字段的size来控制JavaBean对象的大小。本次测试中size=100

2.4  结果

测试A:10000个对象

 
Xml


protobuf


protostuff


序列化


用时(ms)


2399


648


261


占用的CPU(%)


24.2


12.3


3.4


占用的内存(M)


154


235


92


每个文件大小(byte)


2822


574


574


反序列化


用时(ms)


3378


167


224


占用CPU(%)


15.9


14.2


6.1


占用内存(M)


248


307


164


备注:10000个对象

测试B:25000个对象

 
Xml


protobuf


protostuff


序列化


用时(ms)


4161


767


293


占用的CPU(%)


31.2


14.6


4.7


占用的内存(M)


495


228


194


每个文件大小(byte)


2822


574


574


反序列化


用时(ms)


6941


252


393


占用CPU(%)


31.9


21.9


8.1


占用内存(M)


411


382


348


备注:25000个对象

测试C:100000个对象

 
Xml


protobuf


protostuff


序列化


用时(ms)


12867


3070


704


占用的CPU(%)


42.5


44.9


22.3


占用的内存(M)


1098


1058


572


每个文件大小(byte)


2822


574


574


反序列化


用时(ms)


24442


4540


1522


占用CPU(%)


38.8


68.2


24.1


占用内存(M)


2215


597


870


备注:50000个对象

2.5 结论

1、序列化:

  1.1、速度上:protostuff比protobuf快3倍左右,protobuf比xml快4-5倍,该倍数随着序列化对象的增加,基本保持不变。

  1.2、CPU上:protostuff占用最少,protobuf其次,xml最后。

  1.3、内存上:protostuff占用最少,protobuf其次,xml最后。

  1.4、生成文件大小:protostuff占用最少,protobuf其次,xml最后,前面两者是后者的1/4左右。

2、反序列化

  2.1、速度上:在反序列化对象数量较少的情况下,protobuf比protostuff快1/4左右,比xml快10+倍。但随着对象数量的增加,protobuf发生了速率明显变慢的情况!从而被protostuff赶超。

  2.2、CPU上:protostuff占用最少,protobuf其次,xml最后。

  2.3、内存上:protostuff占用最少,protobuf其次,xml最后。

3、总结

  在各个方面上,protostuff的优势非常面试,而protobuf也不弱,考虑用来代替xml。

3、xml简单教程

3.1 准备

jar包:pom.xml:

        <!-- xstream -->
        <dependency>
            <groupId>com.thoughtworks.xstream</groupId>
            <artifactId>xstream</artifactId>
            <version>1.3.1</version>
        </dependency>

3.2 代码

1、java bean:

  1 package com.zjm.www.po;
  2
  3 import java.util.List;
  4
  5 /**
  6  * 商品类
  7  */
  8 public class Products {
  9
 10     private String s1;
 11     private String s2;
 12     private String s3;
 13     private String s4;
 14     private String s5;
 15     private String s6;
 16     private String s7;
 17     private String s8;
 18     private String s9;
 19
 20     private int i1;
 21     private int i2;
 22     private int i3;
 23     private int i4;
 24     private int i5;
 25     private int i6;
 26     private int i7;
 27     private int i8;
 28     private int i9;
 29
 30     private boolean  b1;
 31     private boolean  b2;
 32     private boolean  b3;
 33     private boolean  b4;
 34     private boolean  b5;
 35     private boolean  b6;
 36     private boolean  b7;
 37     private boolean  b8;
 38     private boolean  b9;
 39
 40     private List<String> list;
 41
 42     public String getS1() {
 43         return s1;
 44     }
 45
 46     public void setS1(String s1) {
 47         this.s1 = s1;
 48     }
 49
 50     public String getS2() {
 51         return s2;
 52     }
 53
 54     public void setS2(String s2) {
 55         this.s2 = s2;
 56     }
 57
 58     public String getS3() {
 59         return s3;
 60     }
 61
 62     public void setS3(String s3) {
 63         this.s3 = s3;
 64     }
 65
 66     public String getS4() {
 67         return s4;
 68     }
 69
 70     public void setS4(String s4) {
 71         this.s4 = s4;
 72     }
 73
 74     public String getS5() {
 75         return s5;
 76     }
 77
 78     public void setS5(String s5) {
 79         this.s5 = s5;
 80     }
 81
 82     public String getS6() {
 83         return s6;
 84     }
 85
 86     public void setS6(String s6) {
 87         this.s6 = s6;
 88     }
 89
 90     public String getS7() {
 91         return s7;
 92     }
 93
 94     public void setS7(String s7) {
 95         this.s7 = s7;
 96     }
 97
 98     public String getS8() {
 99         return s8;
100     }
101
102     public void setS8(String s8) {
103         this.s8 = s8;
104     }
105
106     public String getS9() {
107         return s9;
108     }
109
110     public void setS9(String s9) {
111         this.s9 = s9;
112     }
113
114     public int getI1() {
115         return i1;
116     }
117
118     public void setI1(int i1) {
119         this.i1 = i1;
120     }
121
122     public int getI2() {
123         return i2;
124     }
125
126     public void setI2(int i2) {
127         this.i2 = i2;
128     }
129
130     public int getI3() {
131         return i3;
132     }
133
134     public void setI3(int i3) {
135         this.i3 = i3;
136     }
137
138     public int getI4() {
139         return i4;
140     }
141
142     public void setI4(int i4) {
143         this.i4 = i4;
144     }
145
146     public int getI5() {
147         return i5;
148     }
149
150     public void setI5(int i5) {
151         this.i5 = i5;
152     }
153
154     public int getI6() {
155         return i6;
156     }
157
158     public void setI6(int i6) {
159         this.i6 = i6;
160     }
161
162     public int getI7() {
163         return i7;
164     }
165
166     public void setI7(int i7) {
167         this.i7 = i7;
168     }
169
170     public int getI8() {
171         return i8;
172     }
173
174     public void setI8(int i8) {
175         this.i8 = i8;
176     }
177
178     public int getI9() {
179         return i9;
180     }
181
182     public void setI9(int i9) {
183         this.i9 = i9;
184     }
185
186     public boolean isB1() {
187         return b1;
188     }
189
190     public void setB1(boolean b1) {
191         this.b1 = b1;
192     }
193
194     public boolean isB2() {
195         return b2;
196     }
197
198     public void setB2(boolean b2) {
199         this.b2 = b2;
200     }
201
202     public boolean isB3() {
203         return b3;
204     }
205
206     public void setB3(boolean b3) {
207         this.b3 = b3;
208     }
209
210     public boolean isB4() {
211         return b4;
212     }
213
214     public void setB4(boolean b4) {
215         this.b4 = b4;
216     }
217
218     public boolean isB5() {
219         return b5;
220     }
221
222     public void setB5(boolean b5) {
223         this.b5 = b5;
224     }
225
226     public boolean isB6() {
227         return b6;
228     }
229
230     public void setB6(boolean b6) {
231         this.b6 = b6;
232     }
233
234     public boolean isB7() {
235         return b7;
236     }
237
238     public void setB7(boolean b7) {
239         this.b7 = b7;
240     }
241
242     public boolean isB8() {
243         return b8;
244     }
245
246     public void setB8(boolean b8) {
247         this.b8 = b8;
248     }
249
250     public boolean isB9() {
251         return b9;
252     }
253
254     public void setB9(boolean b9) {
255         this.b9 = b9;
256     }
257
258     public List<String> getList() {
259         return list;
260     }
261
262     public void setList(List<String> list) {
263         this.list = list;
264     }
265
266     public Products(){
267
268     }
269
270     public Products(String s1, String s2, String s3, String s4, String s5,
271             String s6, String s7, String s8, String s9, int i1, int i2, int i3,
272             int i4, int i5, int i6, int i7, int i8, int i9, boolean b1,
273             boolean b2, boolean b3, boolean b4, boolean b5, boolean b6,
274             boolean b7, boolean b8, boolean b9, List<String> list) {
275         super();
276         this.s1 = s1;
277         this.s2 = s2;
278         this.s3 = s3;
279         this.s4 = s4;
280         this.s5 = s5;
281         this.s6 = s6;
282         this.s7 = s7;
283         this.s8 = s8;
284         this.s9 = s9;
285         this.i1 = i1;
286         this.i2 = i2;
287         this.i3 = i3;
288         this.i4 = i4;
289         this.i5 = i5;
290         this.i6 = i6;
291         this.i7 = i7;
292         this.i8 = i8;
293         this.i9 = i9;
294         this.b1 = b1;
295         this.b2 = b2;
296         this.b3 = b3;
297         this.b4 = b4;
298         this.b5 = b5;
299         this.b6 = b6;
300         this.b7 = b7;
301         this.b8 = b8;
302         this.b9 = b9;
303         this.list = list;
304     }
305
306     @Override
307     public String toString() {
308         return "Products [s1=" + s1 + ", s2=" + s2 + ", s3=" + s3 + ", s4="
309                 + s4 + ", s5=" + s5 + ", s6=" + s6 + ", s7=" + s7 + ", s8="
310                 + s8 + ", s9=" + s9 + ", i1=" + i1 + ", i2=" + i2 + ", i3="
311                 + i3 + ", i4=" + i4 + ", i5=" + i5 + ", i6=" + i6 + ", i7="
312                 + i7 + ", i8=" + i8 + ", i9=" + i9 + ", b1=" + b1 + ", b2="
313                 + b2 + ", b3=" + b3 + ", b4=" + b4 + ", b5=" + b5 + ", b6="
314                 + b6 + ", b7=" + b7 + ", b8=" + b8 + ", b9=" + b9 + ", list="
315                 + list + "]";
316     }
317 }

2、序列化:

public  List<String> serializeXMLProductsList(List<Products> pList) {
        if(pList == null) {
            System.out.println("【XmlSerializeServiceImpl-serializeProductsListService】pList参数为空");
            return null;
        }
        long start = System.currentTimeMillis() ;
        XStream x = new XStream();
        x.alias("Products", Products.class);
        List<String> strList = new ArrayList<String>();
        for(Products p : pList) {
            String str = x.toXML(p);
            strList.add(str);
        }
        long end = System.currentTimeMillis() ;
        usedTime = end - start ;
        return strList;
    }

3、反序列化

    public List<Products> deserializeXMLDataListToProductsList(
            List<String> xmlStrList) {
        long start = System.currentTimeMillis();
        List<Products> productsList = new ArrayList<Products>();
        XStream xs = new XStream();
        xs.alias("Products", Products.class);
        for(String xmlStr : xmlStrList) {
            Products p = (Products)xs.fromXML(xmlStr);
            productsList.add(p);
        }
        long end = System.currentTimeMillis();
        usedTime = end - start ;
        return productsList;
    }

然而,一般来说,对xstream的序列化和反序列化,要自己实现Converter接口来转化的,这样的解决一个问题,就是对方接口的字段和我们自己的javabean的字段名不一致的问题。这里不多说,可以搜索xstrem Converter,即有大量文章。

4、protobuf简单教程

4.1、快速入门:

  下载.exe编译器——编写.proto文件——利用编译器编译.proto文件生成javabean——引用jar包——直接使用javabean自带的序列化、反序列化方法

1、下载针对java的.exe编译器

protobuf编译器官方下载地址:https://developers.google.com/protocol-buffers/docs/downloads

下载不了的:点我

2、编写.proto文件

package tutorial;
option java_package = "com.zjm.www.po";
option java_outer_classname = "Products2";
message Products22 {
  required string s1 = 1;
  required string s2 = 2;
  required string s3 = 3;
  required string s4 = 4;
  required string s5 = 5;
  required string s6 = 6;
  required string s7 = 7;
  required string s8 = 8;
  required string s9 = 9;
  required int32 i10 = 10;
  required int32 i11 = 11;
  required int32 i12 = 12;
  required int32 i13 = 13;
  required int32 i14 = 14;
  required int32 i15 = 15;
  required int32 i16 = 16;
  required int32 i17 = 17;
  required int32 i18 = 18;
  required bool b19 = 19;
  required bool b20 = 20;
  required bool b21 = 21;
  required bool b22 = 22;
  required bool b23 = 23;
  required bool b24 = 24;
  required bool b25 = 25;
  required bool b26 = 26;
  required bool b27 = 27;
  repeated string list = 28;
}

其中的option java_package代表将要生成的javabean所有的包的包名

其中的option java_outer_classname代表要生成的javabean的类名

其中的message Products22可以理解为一个类似C语言的结构体,在生成的javabean中将变成一个内部类,一个.proto文件可以有无数个message

proto支持的类型与修饰符可参考该博客:http://blog.sina.com.cn/s/blog_abea023b0101dxce.html

3、利用编译器编译.proto文件生成javabean

把.proto文件放在.exe同个目录下面,打开cmd,进入同目录下,执行命令:

protoc.exe --java_out=./ test.proto

假如.proto文件没有编写错误的话,成功后在同目录下即有javabean的类生成。

4、引用jar包

jar包地址pom.xml:

        <!-- protobuf -->
        <dependency>
            <groupId>com.google.protobuf</groupId>
            <artifactId>protobuf-java</artifactId>
            <version>3.0.0-alpha-2</version>
        </dependency>

5、把刚刚生成的javabean复制到项目中,这里直接使用javabean自带的序列化、反序列化方法

刚刚生成的javabean为:Products2

序列化例子:

public List<byte[]> serializeProtoBufProductsList(
            List<Builder> builderList) {
        if(builderList == null) {
            System.out.println("【ProtoBufSerializeServiceImpl-serializeProtoBufProductsService】builderList==null");
        }
        long start = System.currentTimeMillis();
        List<byte[]> bytesList = new ArrayList<byte[]>();
        for(Products2.Products22.Builder p22Builder : builderList){
            Products2.Products22 p22 = p22Builder.build();
            byte[] bytes = p22.toByteArray();
            bytesList.add(bytes);
        }
        long end = System.currentTimeMillis();
        usedTime = end - start ;
        return bytesList;
    }

builder对象由来:com.zjm.www.po.Products2.Products22.Builder,即可有生成的javabean点出来。

反序列化例子:

    public List<Products22> deserializeProtoBufDataListToProducts22List(
            List<byte[]> bytesList) {
        long start = System.currentTimeMillis();
        List<Products22> list = new ArrayList<Products22>();
        for(byte[] b : bytesList) {
            try {
                list.add(Products2.Products22.parseFrom(b));
            } catch (InvalidProtocolBufferException e) {
                e.printStackTrace();
            }
        }
        long end = System.currentTimeMillis();
        usedTime = end - start;
        return list;
    }

拿出具体字段例子:

                Products22 p = Products2.Products22.parseFrom(b);
                String s1 = p.getS1();
                int i1 = p.getI10();
                boolean b1 = p.getB19();
                ProtocolStringList l = p.getListList();

                for(String s : l) {

                }

5、protostuff简单教程

5.1 快速入门

  引用jar包——学习语法——直接使用

1、引用jar包:

pom.xml:

        <!-- protostuff -->
        <dependency>
            <groupId>com.dyuproject.protostuff</groupId>
            <artifactId>protostuff-core</artifactId>
            <version>1.0.7</version>
            <optional>true</optional>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.dyuproject.protostuff</groupId>
            <artifactId>protostuff-runtime</artifactId>
            <version>1.0.7</version>
            <optional>true</optional>
            <scope>provided</scope>
        </dependency>

2、javabean:

同上面xml的javabean

3、序列化例子:

public List<byte[]> serializeProtoStuffProductsList(List<Products> pList) {
        if(pList == null  ||  pList.size() <= 0) {
            return null;
        }
        long start = System.currentTimeMillis() ;
        List<byte[]> bytes = new ArrayList<byte[]>();
        Schema<Products> schema = RuntimeSchema.getSchema(Products.class);
        LinkedBuffer buffer = LinkedBuffer.allocate(4096);
        byte[] protostuff = null;
        for(Products p : pList) {
            try {
                protostuff = ProtostuffIOUtil.toByteArray(p, schema, buffer);
                bytes.add(protostuff);
            } finally {
                buffer.clear();
            }
        }
        long end = System.currentTimeMillis() ;
        this.userTime = end - start;
        return bytes;
    }

4、反序列化例子:

    public List<Products> deserializeProtoStuffDataListToProductsList(
            List<byte[]> bytesList) {
        if(bytesList == null || bytesList.size() <= 0) {
            return null;
        }
        long start = System.currentTimeMillis() ;
        Schema<Products> schema = RuntimeSchema.getSchema(Products.class);
        List<Products> list = new ArrayList<Products>();
        for(byte[] bs : bytesList) {
            Products product = new Products();
            ProtostuffIOUtil.mergeFrom(bs, product, schema);
            list.add(product);
        }
        long end = System.currentTimeMillis() ;
        this.userTime = end - start;
        return list;
    }
时间: 2024-10-07 05:35:48

java序列化/反序列化之xml、protobuf、protostuff 的比较与使用例子的相关文章

java序列化反序列化深入探究

When---什么时候需要序列化和反序列化: 简单的写一个hello world程序,用不到序列化和反序列化.写一个排序算法也用不到序列化和反序列化.但是当你想要将一个对象进行持久化写入文件,或者你想将一个对象从一个网络地址通过网络协议发送到另一个网络地址时,这时候就需要考虑序列化和反序列化了.另外如果你想对一个对象实例进行深度拷贝,也可以通过序列化和反序列化的方式进行. What---什么是序列化和反序列化: Serialization-序列化:可以看做是将一个对象转化为二进制流的过程 Des

java序列化之protobuf

package com.book.core.test; import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; import com.book.core.model.Type; import com.book.core.serializable.SerializationUtil; import com.dyuproject.protostuff.LinkedBuffer; import co

通讯协议序列化解读(二) protostuff详解教程

上一篇文章 通讯协议序列化解读(一):http://www.cnblogs.com/tohxyblog/p/8974641.html  前言:上一面文章我们介绍了java序列化,以及谷歌protobuf,但是由于protobuf的使用起来并不像其他序列化那么简单(首先要写.proto文件,然后编译.proto文件,生成对应的.java文件),所以即使他是如何的优秀,也还是没能抢占json的份额.这篇文章我们要介绍的是一款基于protobuf的java序列化协议--prorostuff,在java

JAVA序列化和反序列化XML

package com.lss.utils; import java.beans.XMLDecoder; import java.beans.XMLEncoder; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; /** * JAVA序列化和反序列化X

JAVA 序列化和反序列化XML

import java.beans.XMLDecoder; import java.beans.XMLEncoder; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; /** * JAVA序列化和反序列化->XML * <p> *公共无参构造函

protostuff序列化/反序列化

Protostuff是基于Google protobuff技术的Java版本,直接使用原生的protobuff是需要数据结构的预编译过程,需要编写.proto格式的配置文件,再通过protobuff提供的工具翻译成目标语言代码,而Protostuff动态支持了protobuff的预编译的过程,可以直接使用普通java POJO进行序列化,简化编码. 经过实测序列化性能相对原生protpbuff没有影响. 由于Protostuff只支持Java实现,不过并未对序列化格式有做任何修改,所以Proto

[java]序列化框架性能对比(kryo、hessian、java、protostuff)

序列化框架性能对比(kryo.hessian.java.protostuff) 简介:   优点 缺点 Kryo 速度快,序列化后体积小 跨语言支持较复杂 Hessian 默认支持跨语言 较慢 Protostuff 速度快,基于protobuf 需静态编译 Protostuff-Runtime 无需静态编译,但序列化前需预先传入schema 不支持无默认构造函数的类,反序列化时需用户自己初始化序列化后的对象,其只负责将该对象进行赋值 Java 使用方便,可序列化所有类 速度慢,占空间      

(记录)Java序列化与反序列化

在学习Redis中的Jedis这一部分的时候,要使用到Protostuff(Protobuf的Java客户端)这一序列化工具.一开始看到序列化这些字眼的时候,感觉到一头雾水.于是,参考了网上的很多资料,理解了Java序列化与反序列化(参考https://blog.csdn.net/wangloveall/article/details/7992448/),Protobuf的作用以及在Java中的使用方法. 1.Java序列化与反序列化是什么: Java序列化是指把Java对象转换为字节序列的过程

XML序列化与反序列化+自定义XML注解框架XmlUtils

背景 前面一篇总结了Serializable的序列化与反序列化,现在接着总结XML.主要内容:XML基本的序列化与反序列化方法.一些注意事项.以及自定义了一个XML注解框架(简洁代码,解放双手). XML的序列化与反序列化 先与Serializable进行简单的对比: Serializable存储的文件,打开后无法正常查看,安全性高.xml文件可通过文本编辑器查看与编辑,可读性高(浏览器会格式化xml文件,更方便查看),安全性低: Serializable文件通过了签名,只能在自己的程序中反序列