关于序列化:几种Java常用序列化框架的选型与对比
简介: 序列化与反序列化是咱们日常数据长久化和网络传输中常常应用的技术,然而目前各种序列化框架让人目迷五色,不分明什么场景到底采纳哪种序列化框架。本文会将业界开源的序列化框架进行比照测试,别离从通用性、易用性、可扩展性、性能和数据类型与Java语法反对五方面给出比照测试。 作者 | 云烨起源 | 阿里技术公众号 一 背景介绍序列化与反序列化是咱们日常数据长久化和网络传输中常常应用的技术,然而目前各种序列化框架让人目迷五色,不分明什么场景到底采纳哪种序列化框架。本文会将业界开源的序列化框架进行比照测试,别离从通用性、易用性、可扩展性、性能和数据类型与Java语法反对五方面给出比照测试。 通用性:通用性是指序列化框架是否反对跨语言、跨平台。易用性:易用性是指序列化框架是否便于应用、调试,会影响开发效率。可扩展性:随着业务的倒退,传输实体可能会发生变化,然而旧实体有可能还会被应用。这时候就须要思考所抉择的序列化框架是否具备良好的扩展性。性能:序列化性能次要包含工夫开销和空间开销。序列化的数据通常用于长久化或网络传输,所以其大小是一个重要的指标。而编解码工夫同样是影响序列化协定抉择的重要指标,因为现在的零碎都在谋求高性能。Java数据类型和语法反对:不同序列化框架所可能反对的数据类型以及语法结构是不同的。这里咱们要对Java的数据类型和语法个性进行测试,来看看不同序列化框架对Java数据类型和语法结构的反对度。上面别离对JDK Serializable、FST、Kryo、Protobuf、Thrift、Hession和Avro进行比照测试。二 序列化框架1 JDK SerializableJDK Serializable是Java自带的序列化框架,咱们只须要实现java.io.Serializable或java.io.Externalizable接口,就能够应用Java自带的序列化机制。实现序列化接口只是示意该类可能被序列化/反序列化,咱们还须要借助I/O操作的ObjectInputStream和ObjectOutputStream对对象进行序列化和反序列化。 上面是应用JDK 序列化框架进行编解码的Demo: 通用性 因为是Java内置序列化框架,所以自身是不反对跨语言序列化与反序列化。 易用性 作为Java内置序列化框架,无序援用任何内部依赖即可实现序列化工作。然而JDK Serializable在应用上相比开源框架难用许多,能够看到下面的编解码应用十分僵硬,须要借助ByteArrayOutputStream和ByteArrayInputStream才能够残缺字节的转换。 可扩展性 JDK Serializable中通过serialVersionUID管制序列化类的版本,如果序列化与反序列化版本不统一,则会抛出java.io.InvalidClassException异样信息,提醒序列化与反序列化SUID不统一。 java.io.InvalidClassException: com.yjz.serialization.java.UserInfo; local class incompatible: stream classdesc serialVersionUID = -5548195544707231683, local class serialVersionUID = -5194320341014913710下面这种状况,是因为咱们没有定义serialVersionUID,而是由JDK主动hash生成的,所以序列化与反序列化前后后果不统一。 然而咱们能够通过自定义serialVersionUID形式来躲避掉这种状况(序列化前后都是应用定义的serialVersionUID),这样JDK Serializable就能够反对字段扩大了。 private static final long serialVersionUID = 1L;性能 JDK Serializable是Java自带的序列化框架,然而在性能上其实一点不像亲生的。上面测试用例是咱们贯通全文的一个测试实体。 public class MessageInfo implements Serializable { private String username; private String password; private int age; private HashMap<String,Object> params; ... public static MessageInfo buildMessage() { MessageInfo messageInfo = new MessageInfo(); messageInfo.setUsername("abcdefg"); messageInfo.setPassword("123456789"); messageInfo.setAge(27); Map<String,Object> map = new HashMap<>(); for(int i = 0; i< 20; i++) { map.put(String.valueOf(i),"a"); } return messageInfo; }}应用JDK序列化后字节大小为:432。光看这组数字兴许不会感觉到什么,之后咱们会拿这个数据和其它序列化框架进行比照。 ...