返回顶部
首页 > 资讯 > 精选 >Java Kryo,Protostuff,Hessian序列化方式是什么
  • 644
分享到

Java Kryo,Protostuff,Hessian序列化方式是什么

2023-07-02 15:07:14 644人浏览 八月长安
摘要

本篇内容主要讲解“Java Kryo,Protostuff,Hessian序列化方式是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java Kryo,Protostuf

本篇内容主要讲解“Java Kryo,Protostuff,Hessian序列化方式是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java Kryo,Protostuff,Hessian序列化方式是什么”吧!

    前言

    前段时间在写rpc框架的时候用到了Kryo、Hessian、Protostuff三种序列化方式。但是当时因为急于实现功能,就只是简单的的看了一下如何使用这三种序列化方式,并没有去深入研究各自的特性,以及优点和缺点。知道现在就将RPC框架写完了之后,才有时间静下心来对三种方式做一个对比,总结

    Kryo、Hessain、Protostuff都是第三方开源的序列化/反序列化框架,要了解其各自的特性,我们首先需要知道序列化/反序列化是什么:

    序列化:就是将对象转化成字节序列的过程。

    反序列化:就是讲字节序列转化成对象的过程。

    seriallization 序列化 : 将对象转化为便于传输的格式, 常见的序列化格式:二进制格式,字节数组JSON字符串,xml字符串。

    deseriallization 反序列化:将序列化的数据恢复为对象的过程

    如果对序列化相关概念还不是很清楚的同学可以参照美团技术团队的序列化和反序列化

    性能对比

    前期准备

    • 我们先创建一个新的Maven项目

    • 然后导入依赖

    <dependency>    <groupId>org.junit.jupiter</groupId>    <artifactId>junit-jupiter-api</artifactId>    <version>5.8.2</version>    <scope>test</scope></dependency><!-- 代码简化 --><dependency>    <groupId>org.projectlombok</groupId>    <artifactId>lombok</artifactId>    <version>1.18.20</version></dependency><!--kryo--><dependency>    <groupId>com.esotericsoftware</groupId>    <artifactId>kryo-shaded</artifactId>    <version>4.0.2</version></dependency><dependency>    <groupId>commons-codec</groupId>    <artifactId>commons-codec</artifactId>    <version>1.10</version></dependency><!--protostuff--><dependency>    <groupId>io.protostuff</groupId>    <artifactId>protostuff-core</artifactId>    <version>1.7.2</version></dependency><dependency>    <groupId>io.protostuff</groupId>    <artifactId>protostuff-runtime</artifactId>    <version>1.7.2</version></dependency><!--hessian2--><dependency>    <groupId>com.caucho</groupId>    <artifactId>hessian</artifactId>    <version>4.0.62</version></dependency>

    工具类:

    kryo

    package cuit.pymjl.utils;import com.esotericsoftware.kryo.Kryo;import com.esotericsoftware.kryo.io.Input;import com.esotericsoftware.kryo.io.Output;import org.apache.commons.codec.binary.Base64;import org.objenesis.strategy.StdInstantiatorStrategy;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.UnsupportedEncodingException;@SuppressWarnings("all")public class KryoUtils {    private static final String DEFAULT_ENCODING = "UTF-8";    //每个线程的 Kryo 实例    private static final ThreadLocal<Kryo> KRYO_LOCAL = new ThreadLocal<Kryo>() {        @Override        protected Kryo initialValue() {            Kryo kryo = new Kryo();                        //支持对象循环引用(否则会栈溢出)            kryo.setReferences(true); //默认值就是 true,添加此行的目的是为了提醒维护者,不要改变这个配置            //不强制要求注册类(注册行为无法保证多个 JVM 内同一个类的注册编号相同;而且业务系统中大量的 Class 也难以一一注册)            kryo.setReGIStrationRequired(false); //默认值就是 false,添加此行的目的是为了提醒维护者,不要改变这个配置            //Fix the NPE bug when deserializing Collections.            ((Kryo.DefaultInstantiatorStrategy) kryo.getInstantiatorStrategy())                    .setFallbackInstantiatorStrategy(new StdInstantiatorStrategy());            return kryo;        }    };        public static Kryo getInstance() {        return KRYO_LOCAL.get();    }    //-----------------------------------------------    //          序列化/反序列化对象,及类型信息    //          序列化的结果里,包含类型的信息    //          反序列化时不再需要提供类型    //-----------------------------------------------        public static <T> byte[] writeToByteArray(T obj) {        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();        Output output = new Output(byteArrayOutputStream);        Kryo kryo = getInstance();        kryo.writeClassAndObject(output, obj);        output.flush();        return byteArrayOutputStream.toByteArray();    }        public static <T> String writeToString(T obj) {        try {            return new String(Base64.encodeBase64(writeToByteArray(obj)), DEFAULT_ENCODING);        } catch (UnsupportedEncodingException e) {            throw new IllegalStateException(e);        }    }        @SuppressWarnings("unchecked")    public static <T> T readFromByteArray(byte[] byteArray) {        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArray);        Input input = new Input(byteArrayInputStream);        Kryo kryo = getInstance();        return (T) kryo.readClassAndObject(input);    }        public static <T> T readFromString(String str) {        try {            return readFromByteArray(Base64.decodeBase64(str.getBytes(DEFAULT_ENCODING)));        } catch (UnsupportedEncodingException e) {            throw new IllegalStateException(e);        }    }    //-----------------------------------------------    //          只序列化/反序列化对象    //          序列化的结果里,不包含类型的信息    //-----------------------------------------------        public static <T> byte[] writeObjectToByteArray(T obj) {        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();        Output output = new Output(byteArrayOutputStream);        Kryo kryo = getInstance();        kryo.writeObject(output, obj);        output.flush();        return byteArrayOutputStream.toByteArray();    }        public static <T> String writeObjectToString(T obj) {        try {            return new String(Base64.encodeBase64(writeObjectToByteArray(obj)), DEFAULT_ENCODING);        } catch (UnsupportedEncodingException e) {            throw new IllegalStateException(e);        }    }        @SuppressWarnings("unchecked")    public static <T> T readObjectFromByteArray(byte[] byteArray, Class<T> clazz) {        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArray);        Input input = new Input(byteArrayInputStream);        Kryo kryo = getInstance();        return kryo.readObject(input, clazz);    }        public static <T> T readObjectFromString(String str, Class<T> clazz) {        try {            return readObjectFromByteArray(Base64.decodeBase64(str.getBytes(DEFAULT_ENCODING)), clazz);        } catch (UnsupportedEncodingException e) {            throw new IllegalStateException(e);        }    }}

    Hessian

    package cuit.pymjl.utils;import com.caucho.hessian.io.Hessian2Input;import com.caucho.hessian.io.Hessian2Output;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.IOException;public class HessianUtils {        public static byte[] serialize(Object obj) {        Hessian2Output ho = null;        ByteArrayOutputStream baos = null;        try {            baos = new ByteArrayOutputStream();            ho = new Hessian2Output(baos);            ho.writeObject(obj);            ho.flush();            return baos.toByteArray();        } catch (Exception ex) {            ex.printStackTrace();            throw new RuntimeException("serialize failed");        } finally {            if (null != ho) {                try {                    ho.close();                } catch (IOException e) {                    e.printStackTrace();                }            }            if (null != baos) {                try {                    baos.close();                } catch (IOException e) {                    e.printStackTrace();                }            }        }    }        public static  <T> T deserialize(byte[] bytes, Class<T> clazz) {        Hessian2Input hi = null;        ByteArrayInputStream bais = null;        try {            bais = new ByteArrayInputStream(bytes);            hi = new Hessian2Input(bais);            Object o = hi.readObject();            return clazz.cast(o);        } catch (Exception ex) {            throw new RuntimeException("deserialize failed");        } finally {            if (null != hi) {                try {                    hi.close();                } catch (IOException e) {                    e.printStackTrace();                }            }            if (null != bais) {                try {                    bais.close();                } catch (IOException e) {                    e.printStackTrace();                }            }        }    }}

    Protostuff

    package cuit.pymjl.utils;import io.protostuff.LinkedBuffer;import io.protostuff.ProtostuffIOUtil;import io.protostuff.Schema;import io.protostuff.runtime.RuntimeSchema;import java.util.Map;import java.util.concurrent.ConcurrentHashMap;public class ProtostuffUtils {        private static final LinkedBuffer BUFFER = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);        private static final Map<Class<?>, Schema<?>> SCHEMA_CACHE = new ConcurrentHashMap<>();        @SuppressWarnings("unchecked")    public static <T> byte[] serialize(T obj) {        Class<T> clazz = (Class<T>) obj.getClass();        Schema<T> schema = getSchema(clazz);        byte[] data;        try {            data = ProtostuffIOUtil.toByteArray(obj, schema, BUFFER);        } finally {            BUFFER.clear();        }        return data;    }        public static <T> T deserialize(byte[] data, Class<T> clazz) {        Schema<T> schema = getSchema(clazz);        T obj = schema.newMessage();        ProtostuffIOUtil.mergeFrom(data, obj, schema);        return obj;    }    @SuppressWarnings("unchecked")    private static <T> Schema<T> getSchema(Class<T> clazz) {        Schema<T> schema = (Schema<T>) SCHEMA_CACHE.get(clazz);        if (schema == null) {            schema = RuntimeSchema.getSchema(clazz);            if (schema == null) {                SCHEMA_CACHE.put(clazz, schema);            }        }        return schema;    }}

    创建一个实体类进行测试:

    package cuit.pymjl.entity;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;import java.io.Serial;import java.io.Serializable;@Data@AllArgsConstructor@NoArgsConstructorpublic class Student implements Serializable {    @Serial    private static final long serialVersionUID = -91809837793898L;    private String name;    private String passWord;    private int age;    private String address;    private String phone;}

    序列化后字节所占空间大小比较

    编写测试类:

    public class MainTest {    @Test    void testLength() {        Student student = new Student("pymjl", "123456", 18, "北京", "123456789");        int kryoLength = KryoUtils.writeObjectToByteArray(student).length;        int hessianLength = HessianUtils.serialize(student).length;        int protostuffLength = ProtostuffUtils.serialize(student).length;        System.out.println("kryoLength: " + kryoLength);        System.out.println("hessianLength: " + hessianLength);        System.out.println("protostuffLength: " + protostuffLength);    }}

    运行截图:

    Java Kryo,Protostuff,Hessian序列化方式是什么

    由图可知,Hessian序列化后字节所占的空间都显著比其他两种方式要大得多

    其他比较

    • Hessian使用固定长度存储int和long,而kryo使用变长的int和long保证这种基本数据类型序列化后尽量小,实际应用中,很大的数据不会经常出现。

    • Kryo进行序列化的时候,需要传入完整类名或者利用 register() 提前将类注册到Kryo上,其类与一个int型的ID相关联,序列中只存放这个ID,因此序列体积就更小,而Hessian则是将所有类字段信息都放入序列化字节数组中,直接利用字节数组进行反序列化,不需要其他参与,因为存的东西多处理速度就会慢点

    • Kryo使用不需要实现Serializable接口,Hessian则需实现

    • Kryo数据类的字段增、减,序列化和反序列化时无法兼容,而Hessian则兼容,Protostuff是只能在末尾添加新字段才兼容

    • Kryo和Hessian使用涉及到的数据类中必须拥有无参构造函数

    • Hessian会把复杂对象的所有属性存储在一个Map中进行序列化。所以在父类、子类存在同名成员变量的情况下,Hessian序列化时,先序列化子类,然后序列化父类,因此反序列化结果会导致子类同名成员变量被父类的值覆盖

    • Kryo不是线程安全的,要通过ThreadLocal或者创建Kryo线程池来保证线程安全,而Protostuff则是线程安全的

    • Protostuff和Kryo序列化的格式有相似之处,都是利用一个标记来记录字段类型,因此序列化出来体积都比较小

    小结

     优点缺点
    Kryo速度快,序列化后体积小跨语言支持较复杂
    Hessian默认支持跨语言较慢
    Protostuff速度快,基于protobuf需静态编译
    Protostuff-Runtime无需静态编译,但序列化前需预先传入schema不支持无默认构造函数的类,反序列化时需用户自己初始化序列化后的对象,其只负责将该对象进行赋值
    Java使用方便,可序列化所有类速度慢,占空间

    到此,相信大家对“Java Kryo,Protostuff,Hessian序列化方式是什么”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

    --结束END--

    本文标题: Java Kryo,Protostuff,Hessian序列化方式是什么

    本文链接: https://lsjlt.com/news/342755.html(转载时请注明来源链接)

    有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

    猜你喜欢
    • Java Kryo,Protostuff,Hessian序列化方式是什么
      本篇内容主要讲解“Java Kryo,Protostuff,Hessian序列化方式是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java Kryo,Protostuf...
      99+
      2023-07-02
    • Java Kryo,Protostuff,Hessian序列化方式对比
      目录前言性能对比前期准备序列化后字节所占空间大小比较其他比较小结前言 前段时间在写RPC框架的时候用到了Kryo、Hessian、Protostuff三种序列化方式。但是当时因为急于...
      99+
      2024-04-02
    • Java高性能序列化工具Kryo怎么使用
      本文小编为大家详细介绍“Java高性能序列化工具Kryo怎么使用”,内容详细,步骤清晰,细节处理妥当,希望这篇“Java高性能序列化工具Kryo怎么使用”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。概述Kryo ...
      99+
      2023-07-02
    • java序列化是什么
      序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。(推荐:java视频教程)序列化是为了解决在对对象流进行读写操作时所引发的问题。序列化的实现:将需要...
      99+
      2018-09-20
      java
    • java 什么是序列化
      简要解释:序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决在对对象流进行读写操作时所引发的问题。序列化的实现:将需要被序列化的类实现...
      99+
      2016-08-15
      java入门 java 序列化
    • Redis的默认序列化方式是什么
      Redis默认的序列化方式是使用简单的字符串。Redis存储的数据都是以字符串的形式进行存储的,包括整数、浮点数、字符串等。Redi...
      99+
      2024-04-29
      Redis
    • Java对象的序列化和反序列化是什么
      这篇文章主要介绍了Java对象的序列化和反序列化是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Java对象的序列化和反序列化是什么文章都会有所收获,下面我们一起来看看吧。Java 对象的序列化和反序列化是...
      99+
      2023-07-06
    • java中序列化与反序列化的作用是什么
      Java中的序列化和反序列化是用来实现对象的持久化存储和网络传输的机制。序列化的作用:1. 对象持久化存储:将Java对象转换为字节...
      99+
      2023-09-15
      java
    • golang序列化和反序列化的方法是什么
      Go语言中序列化和反序列化可以通过将数据转换为字节流格式来实现,常见方法有“JSON序列化和反序列化”、“XML序列化和反序列化”、“gob序列化和反序列化”和“Protocol Buffers序列化和反序列化”四种:1、使用“json.M...
      99+
      2023-12-18
      golang反序列化 golang序列化 Golang go语言
    • java内部类序列化的方法是什么
      Java内部类的序列化方法与普通类的序列化方法并没有太大的区别。Java的序列化机制可以将一个对象转换为字节流,然后可以将字节流写入...
      99+
      2023-10-07
      java
    • Java反序列化对象的方法是什么
      Java中反序列化对象的方法是使用ObjectInputStream类的readObject()方法。可以使用以下步骤来反序列化一个...
      99+
      2023-09-14
      Java
    • golang序列化方法是什么
      这篇文章主要讲解了“golang序列化方法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“golang序列化方法是什么”吧!golang序列化方法有:1、利用Gob包管理gob流,gob...
      99+
      2023-07-04
    • java序列化方式有哪些
      Java序列化方式有以下几种:1. Java默认的序列化:通过实现Serializable接口来实现,默认使用ObjectOutpu...
      99+
      2023-08-15
      java
    • java为什么序列化
      序列化是一种用来处理对象流的机制。 (推荐学习:java课程)所谓对象流:就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于...
      99+
      2015-12-09
      java教程 java
    • fastjson序列化的方法是什么
      Fastjson提供了多种方式进行序列化,常用的有以下几种方法:1. 使用JSON.toJSONString()方法将对象转化为JS...
      99+
      2023-08-16
      fastjson
    • java原生序列化机制是什么
      Java原生序列化机制是一种将对象转换成字节流的过程,以便在网络上进行传输或将对象保存到文件中。通过Java原生序列化机制,可以将对...
      99+
      2023-10-11
      java
    • java序列化的方式有哪些
      Java序列化的方式有:1. 实现Serializable接口:在需要序列化的类中实现Serializable接口,该接口没有任何方...
      99+
      2023-09-27
      java
    • java序列化和反序列化有什么作用
      Java的序列化和反序列化主要用于以下几个方面:1. 数据持久化:可以将Java对象转化为字节序列,并将其写入文件或者数据库,从而实...
      99+
      2023-09-25
      java
    • WCF序列化是什么
      本篇内容介绍了“WCF序列化是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!近期看了大量关于WCF的资料,深入的了解了关于WCF的原理机...
      99+
      2023-06-17
    • PHP中的序列化和反序列化是什么
      这篇“PHP中的序列化和反序列化是什么”文章,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要参考一下,对于“PHP中的序列化和反序列化是什么”,小编整理了以下知识点,请大家跟着小编的步伐一步一步的慢慢理解,接下来就让...
      99+
      2023-06-06
    软考高级职称资格查询
    编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
    • 官方手机版

    • 微信公众号

    • 商务合作