2021-06-28

一个高性能、小而美的序列化工具!

作者:fredalxin
地址:https://fredal.xin/kryo-quickstart

Kryo是一个高性能的序列化/反序列化工具,由于其变长存储特性并使用了字节码生成机制,拥有较高的运行速度和较小的体积,在某些场景中成为了除Json、Protobuf之外的选择。

依赖

首先我们引入maven的相关依赖:

<dependency> <groupId>com.esotericsoftware</groupId> <artifactId>kryo</artifactId> <version>4.0.2</version></dependency>

需要注意的是,由于kryo使用了较高版本的asm,可能会与业务现有依赖的asm产生冲突,这是一个比较常见的问题。只需将依赖改成:

<dependency> <groupId>com.esotericsoftware</groupId> <artifactId>kryo-shaded</artifactId> <version>4.0.2</version></dependency>

记录类型信息

这算是kryo的一个特点,可以把对象信息直接写到序列化数据里,反序列化的时候可以精确地找到原始类信息,不会出错,这意味着在写readxxx方法时,无需传入Class或Type类信息。

相应的,kryo提供两种读写方式。记录类型信息的writeClassAndObject/readClassAndObject方法,以及传统的writeObject/readObject方法。

线程安全

kryo的对象本身不是线程安全的,所以我们有两种选择来保障线程安全。

使用Threadlocal来保障线程安全:

private static final ThreadLocal<Kryo> kryoLocal = new ThreadLocal<Kryo>() {	protected Kryo initialValue() {		Kryo kryo = new Kryo();  kryo.setInstantiatorStrategy(new Kryo.DefaultInstantiatorStrategy(     new StdInstantiatorStrategy()));		return kryo;	};};

或者使用kryo提供的pool:

public KryoPool newKryoPool() { return new KryoPool.Builder(() -> {  final Kryo kryo = new Kryo();  kryo.setInstantiatorStrategy(new Kryo.DefaultInstantiatorStrategy(   new StdInstantiatorStrategy()));  return kryo; }).softReferences().build();}

实例化器

在上面注意到kryo.setInstantiatorStrategy(new Kryo.DefaultInstantiatorStrategy(new StdInstantiatorStrategy())); 这句话显示指定了实例化器。

在一些依赖了kryo的开源软件中,可能由于实例化器指定的问题而抛出空指针异常。例如hive的某些版本中,默认指定了StdInstantiatorStrategy。

public static ThreadLocal<Kryo> runtimeSerializationKryo = new ThreadLocal<Kryo>() { @Override protected synchronized Kryo initialValue() {  Kryo kryo = new Kryo();  kryo.setClassLoader(Thread.currentThread().getContextClassLoader());  kryo.register(java.sql.Date.class, new SqlDateSerializer());  kryo.register(java.sql.Timestamp.class, new TimestampSerializer());  kryo.register(Path.class, new PathSerializer());  kryo.setInstantiatorStrategy(new StdInstantiatorStrategy());  ......   return kryo; };};

而StdInstantiatorStrategy在是依据JVM version信息及JVM vendor信息创建对象的,可以不调用对象的任何构造方法创建对象。

那么例如碰到ArrayList这样的对象时候,就会出问题。观察一下ArrayList的源码:

public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}

既然没有调用构造器,那么这里elementData会是NULL,那么在调用类似ensureCapacity方法时,就会抛出一个异常。

 public void ensureCapacity(int minCapacity) {  if (minCapacity > elementData.length   && !(elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA    && minCapacity <= DEFAULT_CAPACITY)) {   modCount++;   grow(minCapacity);  } }

解决方案很简单,就如框架中代码写的一样,显示指定实例化器,首先使用默认无参构造策略DefaultInstantiatorStrategy,若创建对象失败再采用StdInstantiatorStrategy。

类注册

当kryo写一个对象的实例的时候,默认需要将类的完全限定名称写入。将类名一同写入序列化数据中是比较低效的,所以kryo支持通过类注册进行优化。

kryo.register(SomeClassA.class);kryo.register(SomeClassB.class);kryo.register(SomeClassC.class);

注册会给每一个class一个int类型的Id相关联,这显然比类名称高效,但同时要求反序列化的时候的Id必须与序列化过程中一致。这意味着注册的顺序非常重要。

但是由于现实原因,同样的代码,同样的Class在不同的机器上注册编号任然不能保证一致,所以多机器部署时候反序列化可能会出现问题。

所以kryo默认会禁止类注册,当然如果想要打开这个属性,可以通过kryo.setRegistrationRequired(true);打开。

循环引用

这是对循环引用的支持,可以有效防止栈内存......

原文转载:http://www.shaoqun.com/a/833907.html

跨境电商:https://www.ikjzd.com/

跨境通网站:https://www.ikjzd.com/w/1329

upc:https://www.ikjzd.com/w/111

抢注商标:https://www.ikjzd.com/w/1053


作者:fredalxin地址:https://fredal.xin/kryo-quickstartKryo是一个高性能的序列化/反序列化工具,由于其变长存储特性并使用了字节码生成机制,拥有较高的运行速度和较小的体积,在某些场景中成为了除Json、Protobuf之外的选择。依赖首先我们引入maven的相关依赖:<dependency><groupId>com.esoteri
yiqu:https://www.ikjzd.com/w/210
首信易支付:https://www.ikjzd.com/w/1841
全方位揭秘!什么是亚马逊的Amazon global store?:https://www.ikjzd.com/articles/21977
图文详解:亚马逊账户信用卡信息更换实操:https://www.ikjzd.com/articles/21978
跨境电商小白必看!询盘如何成功转化成订单?:https://www.ikjzd.com/articles/21979
Jumia卖家注意:平台物流放假公告请查收!:https://www.ikjzd.com/articles/21981
女朋友越来越会叫 她快高潮时故意拔出来:http://www.30bags.com/m/a/249922.html
妈妈说一周一次 姐今天晚上就是你的人:http://www.30bags.com/m/a/249789.html
人渣!首尔大学音乐系的一名教授多次对他的研究生进行性骚扰和威胁:http://lady.shaoqun.com/a/390519.html
持续性全身疼痛和感觉减退——可能是脊髓空孔疾病:http://lady.shaoqun.com/a/390520.html
肾结石曾经疼过一次,后来不疼就治好了?医生:也许斯通已经长大了:http://lady.shaoqun.com/a/390522.html
Lazada入驻条件费用&Lazada中国卖家入驻有优势吗?:https://www.ikjzd.com/articles/146098

No comments:

Post a Comment