首页 > 其他分享 >序列化框架-Kyro简述

序列化框架-Kyro简述

时间:2023-01-24 20:45:14浏览次数:37  
标签:kryo Kyro 对象 Kryo 简述 线程 new 序列化

网上有很多资料说 Kryo 只能在 Java 上使用,这点是不对的,事实上除 Java 外,Scala 和 Kotlin 这些基于 JVM 的语言同样可以使用 Kryo 实现序列化。

1.使用方法

(1)添加kyro依赖

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

(2)基本使用概况

Kryo 类会自动执行序列化。Output 类和 Input 类负责处理缓冲字节,并写入到流中。

public class HelloKryo {
    static public void main(String[] args) throws Exception {
        Kryo kryo = new Kryo();
        kryo.register(SomeClass.class);
 
        SomeClass object = new SomeClass();
        object.value = "Hello Kryo!";
 
        Output output = new Output(new FileOutputStream("file.bin"));
        kryo.writeObject(output, object);
        output.close();
 
        Input input = new Input(new FileInputStream("file.bin"));
        SomeClass object2 = kryo.readObject(input, SomeClass.class);
        input.close();
        System.out.println(object2.value);
    }
 
    static public class SomeClass {
        String value;
    }
}

(3)Kyro注册

和很多其他的序列化框架一样,Kryo 为了提供性能减小序列化结果体积,提供注册的序列化对象类的方式。在注册时,会为该序列化类生成 int ID,后续在序列化时使用 int ID 唯一标识该类型。注册的方式如下:

或者

可以明确指定注册类的 int ID,但是该 ID 必须大于等于 0。如果不提供,内部将会使用 int++的方式维护一个有序的 int ID 生成。

2.线程不安全

Kryo 不是线程安全的。每个线程都应该有自己的 Kryo 对象、输入和输出实例。
因此在多线程环境中,可以考虑使用 ThreadLocal 或者对象池来保证线程安全性。

ThreadLocal解决线程不安全

ThreadLocal 是一种典型的牺牲空间来换取并发安全的方式,它会为每个线程都单独创建本线程专用的 kryo 对象。对于每条线程的每个 kryo 对象来说,都是顺序执行的,因此天然避免了并发安全问题。

创建方法如下:

static private final ThreadLocal<Kryo> kryos = new ThreadLocal<Kryo>() {
   protected Kryo initialValue() {
      Kryo kryo = new Kryo();
      // 在此处配置kryo对象的使用示例,如循环引用等
      return kryo;
   };
};
 
Kryo kryo = kryos.get();

之后,仅需要通过 kryos.get() 方法从线程上下文中取出对象即可使用。

对象池解决线程不安全

「池」是一种非常重要的编程思想,连接池、线程池、对象池等都是「复用」思想的体现,通过将创建的“对象”保存在某一个“容器”中,以便后续反复使用,避免创建、销毁的产生的性能损耗,以此达到提升整体性能的作用。
Kryo 对象池原理也是如此。Kryo 框架自带了对象池的实现,整个使用过程不外乎创建池、从池中获取对象、归还对象三步,以下为代码实例。

// Pool constructor arguments: thread safe, soft references, maximum capacity
Pool<Kryo> kryoPool = new Pool<Kryo>(true, false, 8) {
   protected Kryo create () {
      Kryo kryo = new Kryo();
      // Kryo 配置
      return kryo;
   }
};
 
// 获取池中的Kryo对象
Kryo kryo = kryoPool.obtain();
// 将kryo对象归还到池中
kryoPool.free(kryo);

参数分析:

第一个参数用于指定是否在 Pool 内部使用同步,如果指定为 true,则允许被多个线程并发访问。
第三个参数适用于指定对象池的大小的。
第二个参数设置为 true,Kryo 池将会使用 java.lang.ref.SoftReference 来存储对象。这允许池中的对象在 JVM 的内存压力大时被垃圾回收。Pool clean 会删除所有对象已经被垃圾回收的软引用。当没有设置最大容量时,这可以减少池的大小。当池子有最大容量时,没有必要调用 clean,因为如果达到了最大容量,Pool free 会尝试删除一个空引用。

创建完 Kryo 池后,使用 kryo 就变得异常简单了,只需调用 kryoPool.obtain() 方法即可,使用完毕后再调用 kryoPool.free(kryo) 归还对象,就完成了一次完整的租赁使用。
理论上,只要对象池大小评估得当,就能在占用极小内存空间的情况下完美解决并发安全问题。如果想要封装一个 Kryo 的序列化方法,可以参考如下的代码


public static byte[] serialize(Object obj) {
    Kryo kryo = kryoPool.obtain();
    // 使用 Output 对象池会导致序列化重复的错误(getBuffer返回了Output对象的buffer引用)
    try (Output opt = new Output(1024, -1)) {
        kryo.writeClassAndObject(opt, obj);
        opt.flush();
        return opt.getBuffer();
    }finally {
        kryoPool.free(kryo);
    }
}

3.小结

相较于 JDK 自带的序列化方式,Kryo 的性能更快,并且由于 Kryo 允许多引用和循环引用,在存储开销上也更小。
只不过,虽然 Kryo 拥有非常好的性能,但其自身却舍去了很多特性,例如线程安全、对序列化对象的字段修改等。虽然这些弊端可以通过 Kryo 良好的扩展性得到一定的满足,但是对于开发者来说仍然具有一定的上手难度,不过这并不能影响其在 Java 中的地位。

标签:kryo,Kyro,对象,Kryo,简述,线程,new,序列化
From: https://www.cnblogs.com/akai-yuan/p/17066345.html

相关文章

  • Java反序列化-CommonsCollections2利用链分析
    前言接上篇TemplatesImpl利用链分析,学习了通过TemplatesImpl利用链来进行类加载执行恶意代码,现在来学习一下CommonsCollections2利用链。分析前的准备漏洞组件:commons-c......
  • Rust Serde 反序列化的概念
    这几天在捣鼓Serde::Deserializer,发现有一点难理解。死磕了7、8小时后,算是明白了它的原理。如果你也想自己捣鼓,你可以试著把下列两个网址所有代码(代码是以1个简单json反序列......
  • 【Django drf】 序列化类常用字段类和字段参数 定制序列化字段的两种方式 关系表外键
    目录序列化类常用字段类和字段参数常用字段类常用字段参数选项参数通用参数序列化类高级用法之sourcesource填写类中字段source填写模型类中方法source支持跨表查询定制序......
  • 1、[T]C++简述
    C++简述C++是由标准C++委员会通过制定的,它有多个版本,比如C++98,C++11,C++14,C++17,C++20,C++23。读者可以参阅cppreference。本教程的绝大多数内容,事实上都取自这里。在学习......
  • Java反序列化-URLDNS利用链分析
    前言URLDNS链是Java反序列化中比较简单的一个链子,由于URLDNS不依赖第三方包和不限制jdk版本,所以经常用于检测反序列化漏洞。URLDNS并不能执行命令,只能发送DNS请求。(应该......
  • TinyWebserver项目简述
    webserver总结前言:最近做毕设刚好看了这个项目,所以做了一个总结,同时也希望可以帮到其他人。如果本文中有一些概念看不懂,比如说epoll之类的概念,可以自行百度,对这些概念的......
  • drf-Response drf-request.data 序列化类的使用 反序列化新增、修改、删除数据
    目录APIView基本使用使用原生Django写接口(View+JsonResponse)使用drf写接口(APIView+drfResponse)drf两种导入View的方式drfResponseAPIView源码分析Request类源码......
  • Java反序列化-CommonsCollections1利用链分析
    前言学习Java基础语法也有1年多的时间了,Java安全基础也学了有半年了,期间通过ctf赛题学习过fastjson的反序列化并了解了其利用链,但并未深入学习并记录笔记。一直都说要赶......
  • 序列化与反序列化
    序列化与反序列化最近在读麦叔的“python3分钟”,麦叔花了4篇的篇幅来介绍序列化与反序列化,加之本来对序列化的理解就比较含糊,因此今天打算系统的把序列化与反序列化梳理......
  • django获取多对多关系表中字段返回以及序列化器中传参解决方案
    djangohowcanimakeaserializerwithrelationtablefieldhttps://stackoverflow.com/questions/53137077/django-rest-framework-serializer-with-field-from-rela......