【Java SE】| Java 序列化详解

news2024/12/24 0:13:40

目录

  • 🦁 什么是序列化和反序列化?
  • 🦁 序列化和反序列化常见应用场景
  • 🦁 序列化协议对应于 TCP/IP 4 层模型的哪一层?
  • 🦁 常见序列化协议有哪些?
    • 1. Java自带的序列化方式
    • 2. Kryo
    • 3.Hessian

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

如果我们需要持久化 Java 对象比如将 Java 对象保存在文件中,或者在网络传输 Java 对象,这些场景都需要用到序列化。序列化的主要目的是通过网络传输对象或者说是将对象存储到文件系统、数据库、内存中。

简单来说:

  • 序列化:将数据结构或对象转换成二进制字节流的过程
  • 反序列化:将在序列化过程中所生成的二进制字节流转换成数据结构或者对象的过程
    在这里插入图片描述

🦁 序列化和反序列化常见应用场景

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

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

我们先来看各层模型的作用,如下:
在这里插入图片描述
OSI 七层协议模型中,表示层做的事情主要就是对应用层的用户数据进行处理转换为二进制流。反过来的话,就是将二进制流转换成应用层的用户数据。这不就对应的是序列化和反序列化么?
因为,OSI 七层协议模型中的应用层、表示层和会话层对应的都是 TCP/IP 四层模型中的应用层,所以序列化协议属于 TCP/IP 协议应用层的一部分。

🦁 常见序列化协议有哪些?

1. Java自带的序列化方式

在Java中,要使用自带的序列号协议,只需要让需要进行序列化和反序列化的类实现 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只是用来被JVM识别,不会被序列号(被static修饰的变量不会被序列化)

如果不想序列号某些字段,只需要在字段前添加:transient 关键字(只修饰变量)
其作用是阻止实例中那些用此关键字修饰的的变量序列化;当对象被反序列化时,被 transient 修饰的变量值不会被持久化和恢复。

2. Kryo

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

@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;
    });

    @Override
    public 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");
        }
    }

    @Override
    public <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");
        }
    }

}

3.Hessian

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

  1. 引入 Hessian2 相关依赖
<dependency>
    <groupId>com.caucho</groupId>
    <artifactId>hessian</artifactId>
    <version>4.0.38</version>
</dependency>
  1. 创建 Hessian2 序列化/反序列化工具
public class Hessian2SerializationUtil {
    public static byte[] serialize(Object obj) throws IOException {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        Hessian2Output output = new Hessian2Output(outputStream);
        output.writeObject(obj);
        output.flush();
        return outputStream.toByteArray();
    }

    public static <T> T deserialize(byte[] data, Class<T> clazz) throws IOException {
        ByteArrayInputStream inputStream = new ByteArrayInputStream(data);
        Hessian2Input input = new Hessian2Input(inputStream);
        Object obj = input.readObject(clazz);
        return clazz.cast(obj);
    }
}
  1. 使用 Hessian2 序列化/反序列化工具进行数据的编解码
// 对象序列化成字节数组
MyObject obj = new MyObject();
byte[] data = Hessian2SerializationUtil.serialize(obj);

// 字节数组反序列化成对象
MyObject obj = Hessian2SerializationUtil.deserialize(data, MyObject.class);

需要注意的是,在使用 Hessian2 序列化/反序列化工具时,需要引入 Hessian2Output 和 Hessian2Input 两个类,并且序列化时需要将对象写入 ByteArrayOutputStream 中,反序列化时需要从 ByteArrayInputStream 中读取字节数组。另外,在反序列化时,需要指定对象的类型,Hessian2Input 在读取对象时,会根据这个类型信息进行对象的创建和类型检查。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/584303.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Dockerfile(6) - EXPOSE 指令详解

EXPOSE 通知 Docker 容器在运行时监听指定的网络端口 EXPOSE 端口号 EXPOSE 端口号/协议 默认协议是 TCP 同时在 TCP、UDP 上暴露端口 EXPOSE 80/tcp EXPOSE 80/udp EXPOSE 原理 个人理解&#xff1a;EXPOSE 暴露的端口更像是指明了该容器提供的服务需要用到的端口EXPOSE …

独角数卡 搭建-邮件配置-Epusdt配置-收U详细配置

配置独角数卡 https://github.com/assimon/dujiaoka/wiki/2.x_bt_install ⚠️正式上线后一定要将.env配置里面的APP_DEBUG设置为false⚠️ ⚠️正式上线后一定要将.env配置里面的APP_DEBUG设置为false⚠️ ⚠️正式上线后一定要将.env配置里面的APP_DEBUG设置为false⚠️ 安…

FMC子卡设计原理图:141-四路 250Msps 16bits AD FMC子卡 模拟信号、无线电、光电的采集场景

FMC141-四路 250Msps 16bits AD FMC子卡 一、产品概述&#xff1a; 本板卡基于 FMC 标准板卡&#xff0c;实现 4 路 16-bit/250Msps ADC 功能。遵循 VITA 57 标准&#xff0c;板卡可以直接与xilinx公司或者本公司 FPGA 载板连接使用。板卡 ADC 器件采用 ADI 公司 AD9467…

基于关联规则挖掘的商品交叉销售分析

基于关联规则挖掘的商品交叉销售分析 小P&#xff1a;我们最近考虑将一些相关的商品打包销售&#xff0c;以提高GMV&#xff0c;有没有好的方法啊 小H&#xff1a;参考经典的啤酒尿布案例&#xff0c;可以尝试通过关联规则挖掘相关信息 数据探索 # 导入库 import pandas as pd…

创新工具 | 教你6步用故事板设计用户体验事半功倍

问题 构思方案时团队在细节上难以共识 故事板是什么&#xff1f;故事板就像连环画一样&#xff0c;将用户使用解决方案的关键步骤顺序串联了起来&#xff0c;呈现了方案和用户之间的交互。 故事板以先后顺序展现团队票选出来的最佳解决方案&#xff0c;在过程中对于方案中未…

vue 使用vue-json-viewer 展示 JSON 格式数据

vue 使用vue-json-viewer 展示 JSON 格式数据 1、安装 vue-json-viewer插件2、引入插件并注册2.1 全局注册组件2.2 单个页面局部引入 3、插件的基础使用4、插件可选配置说明4.1 选项 4.2 事件4.3 Slots4.4 主题5、实现效果 1、安装 vue-json-viewer插件 npm install vue-json-…

小米新财报:手机承压,转型求生

配图来自Canva可画 近期&#xff0c;国内各互联网大厂、科技公司、电商平台、内容社区等均陆续发布了2023年第一季度财报。在疫情消退、经济回暖的当下&#xff0c;还是有不少企业交出了一份不错的答卷。而国内知名的科技公司——小米集团&#xff0c;由于业务覆盖范围广泛、产…

【线程池】线程池的7种创建方式,详细讲解

文章目录 一、什么是线程池&#xff1f;二、线程池的分类三、线程池的使用四、ThreadPoolExecutor详解 一、什么是线程池&#xff1f; 线程池&#xff08;ThreadPool&#xff09;是一种基于池化思想管理和使用线程的机制。它是将多个线程预先存储在一个“池子”内&#xff0c;…

(哈希表 ) 454. 四数相加 II ——【Leetcode每日一题】

❓454. 四数相加 II 难度&#xff1a;中等 给你四个整数数组 nums1、nums2、nums3 和 nums4 &#xff0c;数组长度都是 n &#xff0c;请你计算有多少个元组 (i, j, k, l) 能满足&#xff1a; 0 < i, j, k, l < nnums1[i] nums2[j] nums3[k] nums4[l] 0 示例 1&a…

如何在多个端口上运行 SSH 服务器?

SSH&#xff08;Secure Shell&#xff09;是一种用于安全远程访问和管理服务器的协议。默认情况下&#xff0c;SSH服务器在Linux系统上使用22号端口进行通信。但是&#xff0c;有时我们可能需要在多个端口上运行SSH服务器&#xff0c;以满足特定的需求或增强服务器的安全性。 本…

Hexo+Twikoo+Vercel 个人博客开启评论功能

Twikoo 文档&#xff1a;https://twikoo.js.org/quick-start.html MongoDB 数据库 点击链接 https://www.mongodb.com/cloud/atlas/register 进入 MongoDB 官网使用邮箱进行注册&#xff1a; 注册之后&#xff0c;MongoDB 会向邮箱发送一封验证邮件&#xff1a; 进入邮箱&…

如何在 Linux 中进行网络地址转换 (NAT)?

网络地址转换&#xff08;Network Address Translation&#xff0c;简称NAT&#xff09;是一种在网络中使用的技术&#xff0c;它允许将私有网络中的IP地址映射到公共网络上&#xff0c;从而实现多个设备共享单个公共IP地址。在Linux系统中&#xff0c;我们可以使用一些工具和配…

实体店引流获客系统模式开发详解

随着互联网的日益发展&#xff0c;实体店的处境变得越来越艰难&#xff0c;获客难和销量差成为了实体店最头疼的两大问题。面对这种情况&#xff0c;一味固步自封是不行的&#xff0c;最好还是顺应潮流&#xff0c;结合一款合适的商业模式&#xff0c;来帮助自己快速引流获客和…

䲟鱼优化算法(ROA)(含MATLAB代码)

先做一个声明&#xff1a;文章是由我的个人公众号中的推送直接复制粘贴而来&#xff0c;因此对智能优化算法感兴趣的朋友&#xff0c;可关注我的个人公众号&#xff1a;启发式算法讨论。我会不定期在公众号里分享不同的智能优化算法&#xff0c;经典的&#xff0c;或者是近几年…

接口测试--apipost接口断言详解

在做接口测试的时候&#xff0c;会对接口进行断言&#xff0c;一个完整的接口测试&#xff0c;包括&#xff1a;请求->获取响应正文->断言。 一、apipost如何进行断言 apipost的断言设置实在后执行脚本中进行编写的。apipost本身提供了11中断言&#xff1a; apt.asser…

经济学基本思维方式

经济学定义 人的欲望是无止境的&#xff0c;而资源有限&#xff0c;这是一个矛盾。 经济学是研究个人和社会如何最优利用由自然和前人提供的有限资源的学问。 经济学的范围 Microeconomics 微观经济学 研究各个行业的运作的以及企业和个人的决策行为的经济学分支。Macroeco…

数据门户基础课程

PC端门户使用示例 首先,以管理员身份登录FineBI系统,安装数据门户,安装步骤见官网 新建一个数据门户

7. Linux系统下在桌面设置添加安装软件启动图标快捷方式

1. 说明 在Linux系统下安装了对应的软件之后&#xff0c;一般启动时需要在命令行终端中进行启动&#xff0c;可以在终端里设置快速启动的命令&#xff0c;相关设置可参考博客&#xff1a;Linux系统下在终端设置快速启动已安装软件。 另一种快捷启动方式就是像在Windows桌面系统…

git报错Filename too long

描述 碰见一个小小问题&#xff0c;Git在拉代码的时候提示Filename too long&#xff0c;具体如图 刚开始&#xff0c;一开始我是使用git自带的那个工具有问题了&#xff0c;然后我就下载了一个tortoisegit&#xff0c;结果还是有问题&#xff0c;这可是22G文件&#xff0c;我…

printf打印彩色字符,还能闪烁!

在使用linux终端命令的时候&#xff0c;我们可以看到像more命令&#xff0c;它的显示方式与一般的字符串不同&#xff0c;是用了反显。同样&#xff0c;linux C下printf还有很多其他不常见的格式化输出形式。本文主要为你盘点这些形式。 效果展示: 特殊的输出 演示代码: #inc…