Java性能优化之序列化优化

news2024/9/22 2:41:35

1、Java 序列化及其缺陷

Java 提供了一种序列化机制,这种机制能够将一个对象序列化为二进制形式(字节数组),用于写入磁盘或输出到网络,同时也能从网络或磁盘中读取字节数组,反序列化成对象,在程序中使用。

JDK 提供的两个输入、输出流对象 ObjectInputStream 和 ObjectOutputStream,它们只能对实现了 Serializable 接口的类的对象进行反序列化和序列化。

在实现了 Serializable 接口的类的对象中,会生成一个 serialVersionUID 的版本号,这个版本号有什么用呢?它会在反序列化过程中来验证序列化对象是否加载了反序列化的类,如果是具有相同类名的不同版本号的类,在反序列化中是无法获取对象的。

 

存在以下缺陷:

1. 无法跨语言

如果是两个基于不同语言编写的应用程序相互通信,则无法实现两个应用服务之间传输对象的序列化与反序列化。

2. 易被攻击

Java 序列化是不安全的,在反序列化字节流的过程中,该方法可以执行任意类型的代码,这是非常危险的。

2015 年 FoxGlove Security 安全团队的 breenmachine 发布过一篇长博客,主要内容是:通过 Apache Commons Collections,Java 反序列化漏洞可以实现攻击。

Apache Commons Collections 就是一个第三方基础库,它扩展了 Java 标准库里的 Collection 结构,提供了很多强有力的数据结构类型,并且实现了各种集合工具类。

实现攻击的原理就是:Apache Commons Collections 允许链式的任意的类函数反射调用,攻击者通过“实现了 Java 序列化协议”的端口,把攻击代码上传到服务器上,再由 Apache Commons Collections 里的 TransformedMap 来执行。

3. 序列化后的流太大

Java 序列后的流会变大,最终会影响到系统的吞吐量。

Java 序列化实现的二进制编码完成的二进制数组大小,比 ByteBuffer 实现的二进制编码完成的二进制数组大小要大上几倍。

4. 序列化性能太差

序列化的速度也是体现序列化性能的重要指标,如果序列化的速度慢,就会影响网络通信的效率,从而增加系统的响应时间。

User user = new User();
    	user.setUserName("test");
    	user.setPassword("test");
    	
    	long startTime = System.currentTimeMillis();
    	
    	for(int i=0; i<1000; i++) {
    		ByteArrayOutputStream os =new ByteArrayOutputStream();
        	ObjectOutputStream out = new ObjectOutputStream(os);
        	out.writeObject(user);
        	out.flush();
        	out.close();
        	byte[] testByte = os.toByteArray();
        	os.close();
    	}
    
    	
    	long endTime = System.currentTimeMillis();
    	System.out.print("ObjectOutputStream 序列化时间:" + (endTime - startTime) + "\n");
long startTime1 = System.currentTimeMillis();
    	for(int i=0; i<1000; i++) {
    		ByteBuffer byteBuffer = ByteBuffer.allocate( 2048);
 
            byte[] userName = user.getUserName().getBytes();
            byte[] password = user.getPassword().getBytes();
            byteBuffer.putInt(userName.length);
            byteBuffer.put(userName);
            byteBuffer.putInt(password.length);
            byteBuffer.put(password);
            
            byteBuffer.flip();
            byte[] bytes = new byte[byteBuffer.remaining()];
    	}
    	long endTime1 = System.currentTimeMillis();
    	System.out.print("ByteBuffer 序列化时间:" + (endTime1 - startTime1)+ "\n");

运行结果:

ObjectOutputStream 序列化时间:29
ByteBuffer 序列化时间:6

通过以上案例,我们可以清楚地看到:Java 序列化中的编码耗时要比 ByteBuffer 长很多。

2、使用 Protobuf 序列化替换 Java 序列化

最近几年比较流行的 Json、Kryo、Protobuf、Hessian 等。这里推荐使用 Protobuf 序列化框架。

Protobuf 是由 Google 推出且支持多语言的序列化框架,目前在主流网站上的序列化框架性能对比测试报告中,Protobuf 无论是编解码耗时,还是二进制流压缩大小,都名列前茅。

Protobuf 以一个 .proto 后缀的文件为基础,这个文件描述了字段以及字段类型,通过工具可以生成不同语言的数据结构文件。在序列化该数据对象的时候,Protobuf 通过.proto 文件描述来生成 Protocol Buffers 格式的编码。

Protobuf 定义了一套自己的编码方式,几乎可以映射 Java/Python 等语言的所有基础数据类型。不同的编码方式对应不同的数据类型,还能采用不同的存储格式。如下图所示:

 

对于存储 Varint 编码数据,由于数据占用的存储空间是固定的,就不需要存储字节长度 Length,所以实际上 Protocol Buffers 的存储方式是 T - V,这样就又减少了一个字节的存储空间。

Protobuf 定义的 Varint 编码方式是一种变长的编码方式,每个数据类型一个字节的最后一位是一个标志位 (msb),用 0 和 1 来表示,0 表示当前字节已经是最后一个字节,1 表示这个数字后面还有一个字节。

对于 int32 类型数字,一般需要 4 个字节表示,若采用 Varint 编码方式,对于很小的 int32 类型数字,就可以用 1 个字节来表示。对于大部分整数类型数据来说,一般都是小于 256,所以这种操作可以起到很好地压缩数据的效果。

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

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

相关文章

无法启动此程序,因为计算机中丢失VCRUNTIME140.dll”错误的解决办法

vcruntime140.dll是什么什么文件呢&#xff1f;为什么电脑在运行一些游戏或许软件的时候会出现丢失vcruntime140.dll&#xff0c;然后游戏或许软件运行失败?这个dll文件是电脑重要的运行库文件。丢失了会导致很多程序无法运行。 首先打开电脑浏览器以后在顶部网页栏目输入&am…

MATLAB实现图像滤波及噪声消除

图像增强是指根据特定的需要突出一幅图像中的某些信息&#xff0c;同时削弱或去除某些不需要的信息的处理方法。其主要目的是使处理后的图像对某种特定的应用来说&#xff0c;比原始图像更适用。因此&#xff0c;这类处理是为了某种应用目的而去改善图像质量的。处理的结果使图…

ROS学习第三十六节——Gazebo仿真环境搭建

https://download.csdn.net/download/qq_45685327/87719408 1.直接添加现成模型 1.1加入环境模型 在工程文件中创建worlds文件夹&#xff0c;并把之前下载的box_house.world文件放入 1.2编写launch文件 deamo03_car_world.launch <launch><!-- 将 Urdf 文件的内容…

CCGNet用于发现共晶材料中的coformer

共晶工程&#xff08;cocrystal engineering&#xff09;在制药&#xff0c;化学和材料领域有广泛应用。然而&#xff0c;如何有效选择coformer一直是一个挑战性课题。因此&#xff0c;作者开发了一个基于GNN的深度学习框架用于快速预测共晶的形成。为了从现有报告的6819个正样…

超详细Redis入门教程——Redis命令(下)

前言 本文小新为大家带来 超详细Redis入门教程——Redis命令 相关知识&#xff0c;具体内容包括简单动态字符串 SDS&#xff0c;集合的底层实现原理&#xff0c;BitMap 操作命令&#xff0c;HyperLogLog 操作命令&#xff0c;Geospatial 操作命令&#xff0c;发布/订阅命令&…

2023.04.23 学习周报

文章目录 摘要文献阅读1.题目2.摘要3.介绍4.模型4.1 研究区域4.2 自相关分析4.3 LSTM 5.实验与讨论5.1 高架道路不同位置空气污染物的变化5.2 高架道路不同位置空气污染物的相关性5.3 高架道路不同位置空气污染物预测 6.结论7.展望 度规张量1.曲率2.度量张量3.代码实现4.平行四…

基于遗传算法的梯级水电站群优化调度研究(Matlab代码实现)

&#x1f4a5; &#x1f4a5; &#x1f49e; &#x1f49e; 欢迎来到本博客 ❤️ ❤️ &#x1f4a5; &#x1f4a5; &#x1f3c6; 博主优势&#xff1a; &#x1f31e; &#x1f31e; &#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 …

王道计组(23版)7_I/O系统

I/O控制方式 数据传输率低的外设&#xff1a; 程序查询方式 程序中断方式&#xff1a;外设准备就绪则主动向CPU发送中断请求 数据传输率高的外设&#xff1a; DMA方式&#xff1a;主存和I/O设备有一条直接数据通路&#xff0c;无需调用中断 通道方式&#xff1a;每个通道挂接若…

CTFSHOW web入门——web30

代码审计 把flag、system、php都给过滤了 passthru()函数同system()函数类似&#xff0c;都可以用来执行外部命令的&#xff0c;因此可以用passthru来代替system。 因此构造payload&#xff1a;?cpassthru(cat f*); 查看页面源代码即可获得flag

ROS学习第三十四节——URDF与Gazebo基本集成流程

https://download.csdn.net/download/qq_45685327/87718593 1.创建功能包 创建新功能包&#xff0c;导入依赖包: urdf xacro gazebo_ros gazebo_ros_control gazebo_plugins 2.编写URDF文件 demo01_helloworld.urdf <robot name"mycar"><link name"…

Android 一个获取网址时间的Demo

Android 一个获取网址时间的Demo 文章目录 Android 一个获取网址时间的Demo通过一个网址获取时间的代码关于Android NTP 时间Android 同步时间代码 前段时间有个客户想用局域网同步Android 设备的时间&#xff0c;开发后把这个demo分享一下。 效果&#xff1a; 这里也获取了阿…

Xshell中的基本命令

whoami 当我们刚登录上Xshell的时候&#xff0c;我们应该做什么呢&#xff1f;&#xff1f; 我们上次说了如何增加使用者&#xff0c;和删除使用者&#xff0c;今天我们说一下其他的基本命令。 我们刚开始登录的时候可以用root登录 那么我们怎么看自己事谁呢&#xff1f; …

C/C++占位符,%x和%p的区别

遇到的问题 今天遇到了一个很奇怪的问题&#xff0c;当使用malloc分配了一个堆空间后&#xff0c;分别尝试用cout和printf尝试打印该地址&#xff0c;出现了两个地址不一样的情况&#xff1a; int *pp (int*)malloc(10*sizeof(int)); *pp 1234; cout << pp << …

35. 搜索插入位置 58. 最后一个单词的长度

目录 35. 搜索插入位置 思路 代码 58. 最后一个单词的长度 思路1 代码1 思路2 代码2 35. 搜索插入位置 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。…

存钱罐出口欧盟CE认证ROHS标准测试

近年来生活水平提高&#xff0c;人们手头上的余钱也多了起来&#xff0c;家长们通常会给小孩子买存钱罐&#xff0c;培养小孩子的理财能力&#xff0c;养成良好的财富观&#xff0c;一般的存钱罐都被设计用来存放硬币&#xff0c;一般分为陶瓷&#xff0c;塑料和金属。上端有缝…

电脑蓝屏怎么办?一招教你修好

很多用户遇到电脑蓝屏问题之后不懂怎么去进行解决&#xff1f;电脑蓝屏之后&#xff0c;我们只需要花一分钟制作一个启动盘&#xff0c;然后用这个启动盘来进行系统的重装就可以了。那么具体要怎么去操作呢&#xff1f;以下带来具体的操作方法教学。 准备工作&#xff1a; 1、U…

备忘录设计模式(Memento Pattern)[论点:概念、组成角色、示例代码、框架中的运用、适用场景]

文章目录 概念组成角色示例代码框架中的运用适用场景 概念 备忘录模式&#xff08;Memento Pattern&#xff09;是一种行为型设计模式&#xff0c;主要用于保存对象的内部状态&#xff0c;以便在需要时恢复到先前的状态。这种模式有助于实现撤销、恢复或回滚操作&#xff0c;同…

软件测试之基础概念学习篇(需求 + 测试用例 + 开发模型 + 测试模型 + BUG)

文章目录 1. 什么是软件测试2. 软件测试和软件开发的区别3. 软件测试和软件调试的区别4. 什么是需求1&#xff09;以需求为依据设计测试用例 5. 测试用例是什么6. 什么是 BUG&#xff08;软件错误&#xff09;7. 五个开发模型1&#xff09;瀑布模型2&#xff09;螺旋模型3&…

有哪些方法可以防止企业内部数据泄露?

企业内部数据安全威胁多数源于企业内部&#xff0c;企业内部存在许多安全威胁&#xff0c;主要包括: 1. 员工误操作或疏忽&#xff1a;这是导致内部安全事故的最主要原因之一。员工对安全程序缺乏认识或执行不严谨&#xff0c;可能会无意中泄露敏感数据或引发系统漏洞。 2. 未经…

Windows 服务监控工具

在任何企业中&#xff0c;Windows 服务都是面向业务的应用程序的核心组件。这些 Windows 服务的有效运行对于防止网络和应用程序停机至关重要。这使得 Windows 服务监视成为任何网络管理策略的关键部分。 Windows 服务监视使管理员能够确保关键 Windows 服务的可用性&#xff…