序列化在高性能网络编程、分布式系统开发中是举足轻重的之前有用过Java序列化、ProtocolBuffer等,在这篇文章这里中简单分析序列化后的byte数组观察各种序列化的差异与性能,这里主要分析Java序列化、Kryo、ProtocolBuffer序列化;

  • Java序列化为jdk自带的序列化实现,不需要依赖任何包;
  • Kryo为高性能开源的Java第三方序列化框架
  • ProtocolBuffer为google开源的数据交换格式,独立于语言,支持Java、Python、C++、C#等

比较性能

说明:使用Java序列化、Kryo、ProtocolBuffer分别序列化、反序列化十万次比较三种方式分别使用的时间;

入口程序:


    public class TestData implements Serializable {
int sn;
public void setSn(int sn) {
this.sn = sn;
}
} public class SerializeCompare { public static void main(String[] args){
TestData testData=new TestData();
testData.setSn(10); SerializeCompare serialize = new SerializeCompare();
try {
serialize.jdkSerialize(testData);
System.out.println("---------------------------------------------------------------");
serialize.kryoTest(testData);
System.out.println("---------------------------------------------------------------");
serialize.protocolTest(); } catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} public void jdkSerialize(TestData testData) throws IOException,
ClassNotFoundException {
JdkSerialize jdkSerialize = new JdkSerialize();
byte[] jdkByte = null;
TestData deSerialize = null;
long startTime = System.currentTimeMillis();
for (int i = 0; i   对比结果发现Java序列化的性能相比其他两种慢了好多,程序跑多次取中间值,java序列化花的时间为kryo的6倍、为ProtoclBuffer的30多倍,kryo相差也是为6倍左右。 程序跑完的结果:



jdk serialize:1259ms

byte length : 68

ac ed 00 05 73 72 00 26 63 6f 2e 73 6f 6c 69 6e 78 2e 64 65 6d 6f 2e 73 65 72 69 61 6c 69 7a 65 2e 64 61 74 61 2e 54 65 73 74 44 61 74 61 4f 17 51 92 bb 30 95 54 02 00 01 49 00 02 73 6e 78 70 00 00 00 0a

kryo serialize:259ms

byte length : 42

01 00 63 6f 2e 73 6f 6c 69 6e 78 2e 64 65 6d 6f 2e 73 65 72 69 61 6c 69 7a 65 2e 64 61 74 61 2e 54 65 73 74 44 61 74 e1 01 14

protocol serialize:44ms

byte length : 2

08 08

分析byte数组

  三种序列化中Java序列化的字节数组是最长的,kryo稍微比Java序列化短一点而ProtocolBuffer的字节数组只有两个字节,下面具体分析每个byte数组;

Java序列化的byte数组

ac ed 00 05 73 72 00 26 63 6f 2e 73 6f 6c 69 6e 78 2e 64 65 6d 6f 2e 73 65 72 69 61 6c 69 7a 65 2e 64 61 74 61 2e 54 65 73 74 44 61 74 61 4f 17 51 92 bb 30 95 54 02 00 01 49 00 02 73 6e 78 70 00 00 00 0a

Java序列化后字节数组三部分组成:开头、类描述、字段值,byte数组中包含了类的版本、元数据、字段描述,字段值等;

开头,所有的对象序列化后都会有,开头与类的描述标识都有在ObjectStreamConstants类中定义有常量;

ac ed : 为幻数

00 05 : 流的版本

类描述

73 : TC_OBJECT 新对象

72 : 新类描述

00 26 : 类名长度

63 6f 2e 73 6f 6c 69 6e 78 2e 64 65 6d 6f 2e 73 65 72 69 61 6c 69 7a 65 2e 64 61 74 61 2e 54 65 73 74 44 61 74 61 :类名 co.solinx.demo.serialize.data.TestData

4f 17 51 92 bb 30 95 54 : serialVersionUID的值

02 : 表示对象支持序列化

00 01 : 表示字段的个数

49 : ASCII码为I,表示字段为int类型

00 02 : 字段名称长度

73 6e : 字段名称:sn

78 : 对象块结束标志,TC ENDBLOCKDATA

70 : 没有父类 TC NULL

00 00 00 0a : 字段sn的值

kryo序列化的byte数组

01 00 63 6f 2e 73 6f 6c 69 6e 78 2e 64 65 6d 6f 2e 73 65 72 69 61 6c 69 7a 65 2e 64 61 74 61 2e 54 65 73 74 44 61 74 e1 01 14

Kryo序列化要比Java序列化简单很多,只有标识+类名+字段三部分组成,对String使用最后一位byte+X70标识String结束;

01 00 : 标识

63 6f 2e 73 6f 6c 69 6e 78 2e 64 65 6d 6f 2e 73 65 72 69 61 6c 69 7a 65 2e 64 61 74 61 2e 54 65 73 74 44 61 74 e1 : 类的名称类名 co.solinx.demo.serialize.data.TestData

01 : 一个字段

14 : 字段的值,反序列化通过 14 >>> 1 ^ -(14 & 1)可以得到值

ProtocolBuffer序列化的byte数组

08 08

  ProtoBuf序列化后只有两个字节,跟前面两种简直没法比,但ProtoBuf和其他两种的序列化区别很大,ProtoBuf为与语言平台无关的,需要编写自定义的proto文件定义数据格式,然后用ProtoBuf编译器编译成目标语言:C++、Java、Python等的代理类,对象的序列化、反序列化都需要使用该类来完成;

  ProtoBuf序列化对象的byte数组由一系列的key-Value组成,key计算公式为:(field_number<<3)|wire_type、Value:经过编码后的byte,ProtoBuf使用了Varint、zigzag编码极大的压缩了序列化后byte数组的大小,所以当前我们看到的byte数组只有08 08 两个字节。

08 : 为key,使用(1<<3)|0计算得到

08 : 为字段sn经过Varint编码后的值

总结

  Java序列化相比Kryo与ProtoBuf序列化后的数组要打得多,速度也慢很多,Java序列化时没有对byte经过任何处理,而且序列化类的元素也太多有:开头、类描述、字段值,类的版本、元数据、字段描述,字段值等这些组成,这也是他byte数组大,速度慢的主要原因;

  Kryo序列化后只有类名和字段信息,相比Java序列化就要简单了不少,而且Kryo对int、long使用了变长存储也节省了不少空间;

  ProtoBuf序列化后的byte只有key-value对组成还使用了Varint、zigzag编码,速度极快,而且占用的空间也极少,但是由于ProtoBuf要编写数据定义文件还要使用ProtoBuf编译器生成目标语言对象,所以相对Java序列化与Kryo来说会麻烦一点;

  用哪种序列化组件主要要是主要取决于需求,如果对跨语言、性能要求比较高、新旧版本兼容要求那这三种中ProtoBuf是不二的选择,如果不要求跨语言对性能又有一定要求那Kryo是不错的选择,如果不跨语言对性能、空间也没有要求那可以选择Java序列化;

  文章首发地址:Solinx

  http://www.solinx.co/archives/377

透过byte数组简单分析Java序列化、Kryo、ProtoBuf序列化的更多相关文章

  1. 简单分析Java的HashMap.entrySet()的实现

    关于Java的HashMap.entrySet(),文档是这样描述的:这个方法返回一个Set,这个Set是HashMap的视图,对Map的操作会在Set上反映出来,反过来也是.原文是 Returns ...

  2. 简单分析Java中审批业务流程业务原理

  3. 图片和byte[]数组互转

    一.图片转成byte[]数组. import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io ...

  4. Redis入门 – Jedis存储Java对象 - (Java序列化为byte数组方式)

    Redis入门 – Jedis存储Java对象 - (Java序列化为byte数组方式) 原文地址:http://alanland.iteye.com/admin/blogs/1600685(欢迎转载 ...

  5. 深度分析 Java 的枚举类型:枚举的线程安全性及序列化问题(转)

    写在前面: Java SE5 提供了一种新的类型 Java的枚举类型,关键字 enum 可以将一组具名的值的有限集合创建为一种新的类型,而这些具名的值可以作为常规的程序组件使用,这是一种非常有用的功能 ...

  6. java 中 “文件” 和 “流” 的简单分析

    java 中 FIle 和 流的简单分析 File类 简单File 常用方法 创建一个File 对象,检验文件是否存在,若不存在就创建,然后对File的类的这部分操作进行演示,如文件的名称.大小等 / ...

  7. 深度分析Java的枚举类型—-枚举的线程安全性及序列化问题

    原文:深度分析Java的枚举类型--枚举的线程安全性及序列化问题 枚举是如何保证线程安全的 要想看源码,首先得有一个类吧,那么枚举类型到底是什么类呢?是enum吗?答案很明显不是,enum就和clas ...

  8. java:java静态代理与动态代理简单分析

    java静态代理与动态代理简单分析 转载自:http://www.cnblogs.com/V1haoge/p/5860749.html 1.动态代理(Dynamic Proxy) 代理分为静态代理和动 ...

  9. Java:对一个对象序列化和反序列化的简单实现

    名词解释 序列化:将Java对象转化成字节的过程 反序列化:将字节转化成Java对象的过程 字节:1字节(byte)= 8bit,bit就是计算机认识的二进制 序列化的作用 Java对象是在Java虚 ...

随机推荐

  1. 代码与图详解性能之Python集合类型(list tuple dict set generator)

    Python内嵌的集合类型有list.tuple.set.dict. 列表list:看似数组,但比数组强大,支持索引.切片.查找.增加等功能. 元组tuple:功能跟list差不多,但一旦生成,长度及 ...

  2. Effective Java

    Effective Java 创建和销毁对象---考虑用静态工厂方法代替构造器 构造器是创建一个对象实例最基本也最通用的方法,大部分开发者在使用某个class的时候,首先需要考虑的就是如何构造和初始化 ...

  3. 字符串模板替换方法 MessageFormat.format

    String content = "ab,cc,{名称},{密码},{日期},dd,ff"; String array[] = {userName, password, forma ...

  4. mysql出错:Access denied for user 'root'@'localhost' (using password: YES)

    网站链接mysql数据库的时候,连接不上,并报出错误:Access denied for user 'root'@'localhost' (using password:YES) 这是个相当恼火的问题 ...

  5. C#的库存管理之旅的别样意义

    我不知道大家对C#的一些基础知识掌握得怎么样了? 但无论怎么样,都应该静心下来去慢慢品味我的总结以及“库存管理”项目需用到的一些知识和技巧.你将会得到你料想不到的收获哦. 知识梳理: 数据类型:boo ...

  6. 创业小坑:内网域名 在windows下能nslookup,但ping不通,也无法访问。而在linux下正常。

    使用巴法络(BUFFALO )LS-XL 网络硬盘盒开启了FTP服务,IP是172.16.0.21 在windows和linux上,都可以访问ftp://172.16.0.21,现在想使用域名访问,便 ...

  7. 【今日推荐】移动 Web 开发的10个最佳 JavaScript 框架

    选择正确的 JavaScript 框架,对于开发移动 Web 应用程序是至关重要的,也是移动应用程序开发的一项重要任务.开发人员可以使用框架实现的功能高效地达到他们的开发目标.这些预实现的组件采用优秀 ...

  8. 未来的 Web:九个不可思议的 WebGL 应用试验

    WebGL 技术允许把 JavaScript 和 OpenGL ES 2.0 结合在一起,通过增加 OpenGL ES 2.0 的一个 JavaScript 绑定,WebGL 可以为 HTML5 Ca ...

  9. MongoDB,客户端工具备份数据库

    本篇介绍下如何利用客户端工具来进行远程服务器的数据备份到本地. 以客户端工具MongoVUE为例来进行讲解: 1.首先要连接本地服务器以及远程服务器数据库 2.在本地服务器(127.0.0.1)中,右 ...

  10. 【Bootstrap】1.初识Bootstrap

    作为Web前端开发框架,Bootstrap为大多数标准的UI设计常见提供了用户友好.扩浏览器的解决方案. 1.下载Bootstrap 打开官方网址 http://getbootstrap.com/ 进 ...