序列化和反序列化相关概念

什么是序列化?什么是反序列化?

如果我们需要持久化Java对象比如将Java对象保存在文件中,或者在网络传输Java对象,这些场景都需要用到序列化。

简单来说:

  • 序列化: 将数据结构或对象转换成二进制字节流的过程
  • 反序列化:将在序列化过程中所生成的二进制字节流的过程转换成数据结构或者对象的过程

对于Java这种面向对象编程语言来说,我们序列化的都是对象(Object)也就是实例化后的类(Class),但是在C++这种半面向对象的语言中,struct(结构体)定义的是数据结构类型,而class 对应的是对象类型。

维基百科是如是介绍序列化的:

序列化(serialization)在计算机科学的数据处理中,是指将数据结构或对象状态转换成可取用格式(例如存成文件,存于缓冲,或经由网络中发送),以留待后续在相同或另一台计算机环境中,能恢复原先状态的过程。依照序列化格式重新获取字节的结果时,可以利用它来产生与原始对象相同语义的副本。对于许多对象,像是使用大量引用的复杂对象,这种序列化重建的过程并不容易。面向对象中的对象序列化,并不概括之前原始对象所关系的函数。这种过程也称为对象编组(marshalling)。从一系列字节提取数据结构的反向操作,是反序列化(也称为解编组、deserialization、unmarshalling)。

综上:序列化的主要目的是通过网络传输对象或者说是将对象存储到文件系统、数据库、内存中。

实际开发中有哪些用到序列化和反序列化的场景?

  1. 对象在进行网络传输(比如远程方法调用RPC的时候)之前需要先被序列化,接收到序列化的对象之后需要再进行反序列化;
  2. 将对象存储到文件中的时候需要进行序列化,将对象从文件中读取出来需要进行反序列化。
  3. 将对象存储到缓存数据库(如 Redis)时需要用到序列化,将对象从缓存数据库中读取出来需要反序列化。

序列化协议对应于TCP/IP 4层模型的哪一层?

我们知道网络通信的双方必须要采用和遵守相同的协议。TCP/IP 四层模型是下面这样的,序列化协议属于哪一层呢?

  1. 应用层
  2. 传输层
  3. 网络层
  4. 网络接口层

如上图所示,OSI七层协议模型中,表示层做的事情主要就是对应用层的用户数据进行处理转换为二进制流。反过来的话,就是将二进制流转换成应用层的用户数据。这不就对应的是序列化和反序列化么?

因为,OSI七层协议模型中的应用层、表示层和会话层对应的都是TCP/IP 四层模型中的应用层,所以序列化协议属于TCP/IP协议应用层的一部分。

常见序列化协议对比

JDK自带的序列化方式一般不会用 ,因为序列化效率低并且部分版本有安全漏洞。比较常用的序列化协议有 hessian、kyro、protostuff。

下面提到的都是基于二进制的序列化协议,像 JSON 和 XML这种属于文本类序列化方式。虽然 JSON 和 XML可读性比较好,但是性能较差,一般不会选择。

JDK自带的序列化方式

JDK 自带的序列化,只需实现 java.io.Serializable接口即可。

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Builder
@ToString
public class RpcRequest implements Serializable {private static final long serialVersionUID = 1905122041950251207L;private String requestId;private String interfaceName;private String methodName;private Object[] parameters;private Class<?>[] paramTypes;private RpcMessageTypeEnum rpcMessageTypeEnum;
}

序列化号 serialVersionUID 属于版本控制的作用。序列化的时候serialVersionUID也会被写入二级制序列,当反序列化时会检查serialVersionUID是否和当前类的serialVersionUID一致。如果serialVersionUID不一致则会抛出 InvalidClassException 异常。强烈推荐每个序列化类都手动指定其 serialVersionUID,如果不手动指定,那么编译器会动态生成默认的序列化号

我们很少或者说几乎不会直接使用这个序列化方式,主要原因有两个:

  1. 不支持跨语言调用 : 如果调用的是其他语言开发的服务的时候就不支持了。
  2. 性能差 :相比于其他序列化框架性能更低,主要原因是序列化之后的字节数组体积较大,导致传输成本加大。

Kryo

Kryo是一个高性能的序列化/反序列化工具,由于其变长存储特性并使用了字节码生成机制,拥有较高的运行速度和较小的字节码体积。

另外,Kryo 已经是一种非常成熟的序列化实现了,已经在Twitter、Groupon、Yahoo以及多个著名开源项目(如Hive、Storm)中广泛的使用。

guide-rpc-framework

就是使用的 kyro 进行序列化,序列化和反序列化相关的代码如下:

/*** Kryo serialization class, Kryo serialization efficiency is very high, but only compatible with Java language*/
@Slf4j
public class KryoSerializer implements Serializer {/*** Because Kryo is not thread safe. So, use ThreadLocal to store Kryo objects*/private final ThreadLocal<Kryo> kryoThreadLocal = ThreadLocal.withInitial(() -> {Kryo kryo = new Kryo();kryo.register(RpcResponse.class);kryo.register(RpcRequest.class);return kryo;});@Overridepublic byte[] serialize(Object obj) {try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();Output output = new Output(byteArrayOutputStream)) {Kryo kryo = kryoThreadLocal.get();// Object->byte:将对象序列化为byte数组kryo.writeObject(output, obj);kryoThreadLocal.remove();return output.toBytes();} catch (Exception e) {throw new SerializeException("Serialization failed");}}@Overridepublic <T> T deserialize(byte[] bytes, Class<T> clazz) {try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);Input input = new Input(byteArrayInputStream)) {Kryo kryo = kryoThreadLocal.get();// byte->Object:从byte数组中反序列化出对对象Object o = kryo.readObject(input, clazz);kryoThreadLocal.remove();return clazz.cast(o);} catch (Exception e) {throw new SerializeException("Deserialization failed");}}}

Protobuf

Protobuf出自于Google,性能还比较优秀,也支持多种语言,同时还是跨平台的。就是在使用中过于繁琐,因为你需要自己定义 IDL 文件和生成对应的序列化代码。这样虽然不然灵活,但是,另一方面导致protobuf没有序列化漏洞的风险。

Protobuf包含序列化格式的定义、各种语言的库以及一个IDL编译器。正常情况下你需要定义proto文件,然后使用IDL编译器编译成你需要的语言

一个简单的 proto 文件如下:

// protobuf的版本
syntax = "proto3";
// SearchRequest会被编译成不同的编程语言的相应对象,比如Java中的class、Go中的struct
message Person {//string类型字段string name = 1;// int 类型字段int32 age = 2;
}

ProtoStuff

由于Protobuf的易用性,它的哥哥 Protostuff 诞生了。

protostuff 基于Google protobuf,但是提供了更多的功能和更简易的用法。虽然更加易用,但是不代表 ProtoStuff 性能更差。

hession

hessian 是一个轻量级的,自定义描述的二进制RPC协议。hessian是一个比较老的序列化实现了,并且同样也是跨语言的。

[图片上传失败…(image-16256e-1650447513453)]

dubbo RPC默认启用的序列化方式是 hession2 ,但是,Dubbo对hessian2进行了修改,不过大体结构还是差不多。

总结

Kryo 是专门针对Java语言序列化方式并且性能非常好,如果你的应用是专门针对Java语言的话可以考虑使用,并且 Dubbo 官网的一篇文章中提到说推荐使用 Kryo 作为生产环境的序列化方式。

像Protobuf、 ProtoStuff、hession这类都是跨语言的序列化方式,如果有跨语言需求的话可以考虑使用。

除了我上面介绍到的序列化方式的话,还有像 Thrift,Avro 这些。

在此我向大家推荐一个架构学习交流圈。交流学习微信:539413949(里面有大量的面试题及答案)里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化、分布式架构等这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

Java 序列化详解相关推荐

  1. Java集合排序及java集合类详解

    Java集合排序及java集合类详解 (Collection, List, Set, Map) 摘要内容 集合是Java里面最常用的,也是最重要的一部分.能够用好集合和理解好集合对于做Java程序的开 ...

  2. MySQL隔离级别--未提交读,提交读,可重复读,序列化--详解(有示例)

    原文网址:MySQL隔离级别--未提交读,提交读,可重复读,序列化--详解(有示例)_IT利刃出鞘的博客-CSDN博客 简介          本文介绍MySQL的事务隔离级别的含义,并用示例说明各个 ...

  3. Apache Thrift - java开发详解

    2019独角兽企业重金招聘Python工程师标准>>> Apache Thrift - java开发详解 博客分类: java 架构 中间件 1.添加依赖 jar <depen ...

  4. Java泛型详解-史上讲解最详细的,没有之一

    目录 1. 概述 2. 一个栗子 3. 特性 4. 泛型的使用 4.1 泛型类 4.2 泛型接口 4.3 泛型通配符 4.4 泛型方法 4.4.1 泛型方法的基本用法 4.4.2 类中的泛型方法 4. ...

  5. Java虚拟机详解----JVM常见问题总结

    [正文] 声明:本文只是做一个总结,有关jvm的详细知识可以参考本人之前的系列文章,尤其是那篇:Java虚拟机详解04----GC算法和种类.那篇文章和本文是面试时的重点. 面试必问关键词:JVM垃圾 ...

  6. java 泛型详解、Java中的泛型方法、 java泛型详解

    本文参考java 泛型详解.Java中的泛型方法. java泛型详解 概述 泛型在java中有很重要的地位,在面向对象编程及各种设计模式中有非常广泛的应用. 什么是泛型?为什么要使用泛型? 泛型,即& ...

  7. 最详细的java泛型详解

    来源:最详细的java泛型详解 对java的泛型特性的了解仅限于表面的浅浅一层,直到在学习设计模式时发现有不了解的用法,才想起详细的记录一下. 本文参考java 泛型详解.Java中的泛型方法. ja ...

  8. Java异常详解及如何处理

    来源:Java异常详解及如何处理 简介 程序运行时,发生的不被期望的事件,它阻止了程序按照程序员的预期正常执行,这就是异常.异常发生时,是任程序自生自灭,立刻退出终止,还是输出错误给用户?或者用C语言 ...

  9. Java基础——Java NIO详解(一)

    一.基本概念 1.I/0简介 I/O即输入输出,是计算机与外界世界的一个借口.IO操作的实际主题是操作系统.在java编程中,一般使用流的方式来处理IO,所有的IO都被视作是单个字节的移动,通过str ...

最新文章

  1. python字符串写入excel-使用python将数据写入excel
  2. 网站性能分析(下)-让网站并行加载但顺序执行JS
  3. Java内存泄露的理解与解决
  4. c#基础知识第十一节
  5. 10个Linux 系统性能监控命令行工具
  6. Windows 下安装 Redis 1
  7. Stanford CoreNLP - 自然语言软件
  8. FRR BGP协议分析9 -- FLOW SPEC
  9. 用matlab产生hdb3码,MATLAB仿真 HDB3码程序
  10. 什么是容器服务_即学即用Docker(一):说说容器和Docker
  11. spss分析方法-相关分析(转载)
  12. 艾司博讯:拼多多商家sku编码是什么意思
  13. 网络安全工程师面试总结
  14. java freemarker 动态生成word,再转pdf
  15. 区块链技术工坊 - 线下区块链技术分享
  16. Linux NFS存储服务详解
  17. linux 安装opanwrt虚拟机,Openwrt使用-虚拟机使用IMG镜像安装系统
  18. 2022-2027年中国消防器材制造行业发展前景及投资战略咨询报告
  19. 推荐这款,SpringBoot 开源商城系统,挣钱太轻松了
  20. 配置Kafka发送大消息

热门文章

  1. EAP-TTLS预研报告
  2. cocoapods was not able to update the 'master' repo.if it is a unexpected issue and persists you can
  3. vue基础:ElementUI的表单
  4. 小程序审核出现的虚拟支付审核失败
  5. java插入背景图片问题_java程序中如何插入背景图片
  6. 【转】为什么你的硬盘容易坏?因为它转得实在是太快了
  7. 苹果或研发第二代智能手表
  8. FCPX视频剪辑Final Cut Pro X v10.5.4中文版 Macbook支持Silicon M1 附详细安装教程
  9. 3D导航栏翻转(css)
  10. “大多数”餐馆收银系统被用于盗用信用卡信息的恶意软件感染