Java 序列化详解

2023-10-28

Java 序列化(Serialization)是指将一个 Java 对象转换成字节序列,以便在网络上传输或存储在本地磁盘中。而反序列化(Deserialization)则是将已经序列化的字节序列恢复为 Java 对象。Java 提供了自带的序列化机制,可以通过实现 Serializable 接口以及使用 ObjectOutputStream 和 ObjectInputStream 类来实现序列化和反序列化。

1. 序列化的基本概念和使用方法

1.1 基本概念

Java 序列化的基本概念包括以下几个方面:

  • 序列化:将一个对象转换为二进制数据流,方便进行网络传输、磁盘存储等操作。
  • 反序列化:将序列化后的二进制数据流还原成原来的对象,重新获取对象的引用。
  • Serializable 接口:Java 提供的标记接口,用于标识一个类可以被序列化。
  • serialVersionUID:用于识别版本之间的兼容性,防止序列化和反序列化的版本不一致导致出错。
  • transient 关键字:标记一个字段不需要进行序列化。

1.2 使用方法

Java 序列化的使用方法如下:

  1. 定义一个需要序列化的类,并实现 Serializable 接口:
public class User implements Serializable {
    private static final long serialVersionUID = 1L;
    
    private String name;
    private int age;
    
    // getters and setters
}
  1. 创建一个 ObjectOutputStream 对象,并将需要序列化的对象写入到输出流中:
User user = new User();
user.setName("Tom");
user.setAge(18);

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user.ser"));
oos.writeObject(user);
oos.close();
  1. 创建一个 ObjectInputStream 对象,并从输入流中读取序列化后的对象:
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user.ser"));
User user = (User) ois.readObject();
ois.close();

2. 序列化的实现原理和注意事项

2.1 实现原理

Java 序列化的实现原理可以简单地概括为:将对象的状态以二进制格式保存在文件中,以便在需要时恢复该对象的状态。

在具体实现中,Java 序列化包括以下几个步骤:

  1. 创建一个 ObjectOutputStream 对象,用于将对象写入输出流中。
  2. ObjectOutputStream 对象首先会检查对象是否为 null,如果是 null,则会直接写入一个 null 标记。
  3. ObjectOutputStream 对象会获取对象的类信息,并将其写入输出流中。
  4. ObjectOutputStream 对象会根据对象的类信息,获取对象的每个字段,并将其写入输出流中,如果某个字段被标记为 transient,则不进行序列化。对于包含其他对象的字段,递归执行序列化操作。
  5. ObjectOutputStream 对象在写入对象的所有字段之后,会写入一个结束标记。

2.2 注意事项

在 Java 序列化过程中,有以下几个注意事项:

  1. 需要序列化的类必须实现 Serializable 接口。
  2. serialVersionUID 用于判断序列化和反序列化的版本是否一致,建议长期保存。
  3. transient 关键字用于标识一个字段不需要进行序列化。
  4. 序列化操作是有代价的,如果需要频繁地进行序列化操作,需要考虑到性能问题。
  5. 序列化后的文件可以在网络中传输,但需要注意安全问题。

3. 反序列化的基本概念和使用方法

3.1 基本概念

Java 反序列化的基本概念包括以下几个方面:

  • 反序列化:将序列化后的二进制数据流还原成原来的对象,重新获取对象的引用。
  • ObjectInputStream 类:用于从输入流中读取序列化后的对象。
  • readObject() 方法:用于从输入流中读取序列化后的对象,返回 Object 类型的对象。

3.2 使用方法

Java 反序列化的使用方法如下:

  1. 创建一个 ObjectInputStream 对象,并从输入流中读取序列化后的对象:
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user.ser"));
User user = (User) ois.readObject();
ois.close();

4. 反序列化中的安全问题以及如何避免

4.1 安全问题

Java 序列化和反序列化在网络传输等场景中广泛使用,但同时也存在一些安全问题。例如,Java 序列化在反序列化时会自动执行对象中的构造函数,从而可能导致安全漏洞。攻击者可以通过构造恶意数据,使得反序列化操作执行他们所期望的恶意情况,从而实现攻击目的。

比较常见的攻击类型包括:

  • 远程执行代码(Remote Code Execution,RCE):使用序列化和反序列化机制,向另一个 Java 程序发送一个“恶意”对象,使得对方程序以攻击者的意愿执行代码。
  • 反序列化注入(Deserialization Injection):攻击者通过在序列化文件中插入特定的序列化对象来引发反序列化操作,并实现对目标应用系统的攻击。

4.2 避免安全问题

避免 Java 序列化和反序列化中的安全问题可以采取以下一些措施:

  1. 不要信任远程传输的数据:在反序列化前,应该验证序列化数据的源头,确保其来源可靠。
  2. 使用白名单来限制反序列化的类:在反序列化时使用白名单来限制可反序列化的类,只允许反序列化特定的类。
  3. 尽量避免序列化敏感数据:尽量避免将敏感数据序列化到文件或网络中,而是采用加密等方式来保护数据的安全性。
  4. 升级 JDK 版本:从 JDK8 开始,Java 系统已经默认禁止使用无效的 serialVersionUID 来验证序列化版本号,而是自动生成一个新的 serialVersionUID。

综上所述,Java 序列化和反序列化是 Java 编程中重要的一个部分,在需要进行对象的跨进程、跨网络传输等场景中,会带来很大的便利。但是在使用过程中,需要注意安全问题,并对可能的安全漏洞进行防范。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java 序列化详解 的相关文章

  • 如何正确地将MapStruct与Eclipse集成? (包括Lombok java代理)

    我愿意在一些官方项目中使用MapStruct 所以我决定先对其进行一些测试 我需要让它与 eclipse 集成工作 并遵循 MapStruct 网站上提供的所有说明 但是 到目前为止还没有运气 有人成功实现了这种整合吗 如果是的话我可以缺少
  • 如何制作具有两个索引的 Map?

    我在java中有一张这样的地图 Map
  • Java 增强型 For-Loop 比传统的更快?

    所以我的理解是 增强的 for 循环应该更慢 因为它们必须使用迭代器 但是我的代码提供了混合结果 是的 我知道循环逻辑占用了循环中花费的大部分时间 对于少量迭代 100 1000 增强的 for 循环在使用和不使用 JIT 的情况下似乎都要
  • HashMap何时以及如何将桶从链表转换为红黑树? [复制]

    这个问题在这里已经有答案了 我正在研究 java 8 功能 发现当存储桶上的条目集数量增加时 哈希图使用红黑树而不是链表 但是 这是否不需要密钥是可比较的或存在某种密钥排序以及这是如何工作的 这种转变何时真正发生以及如何发生 当有at le
  • 如何在我的 HttpClient 执行器中遵循单一职责原则?

    我在用RestTemplate http docs spring io spring docs current javadoc api org springframework web client RestTemplate html as
  • 堆内存与对象内存

    根据一篇关于Java内存和特性的论文 内存分数分为两种类型 堆内存 即应用程序在运行时消耗的内存 对象内存 即程序中使用的各种对象分配的内存 例如整数和字符串等 他们的意思是stack当他们说时的记忆object记忆 或者它们是什么意思 很
  • IDEA:javac:源版本1.7需要目标版本1.7

    使用 IntelliJ IDEA 运行 JUnit 测试时 我得到 我该如何纠正这个问题 使用SDK 1 7 模块语言级别为1 7 Maven 构建工作正常 这就是为什么我相信IDEA配置问题 您很可能在此处从 Maven 导入了不正确的编
  • 注释处理器可以用于代码生成吗?

    假设我定义了一个名为 MyAnnotation 有一个班级X其声明为 MyAnnotation class X 现在在编译时我想检查所有带有注释的类 MyAnnotation并对更多需要在同一进程中编译的 java 源文件进行一些代码生成
  • Java 中内存高效的稀疏数组

    关于时间高效的稀疏数组存在一些问题 但我正在寻找内存效率 我需要相当于List
  • Spring Security登录返回404

    我目前正在使用 Spring 框架开发我的博客 我正在实现 Spring Security 用于登录目的 一切都按预期进行 直到我提交始终返回 404 代码的登录凭据 这是我的 web xml 代码e
  • 获取 n 元组中的所有 1-k 元组

    当 n 5 且 k 3 时 以下循环将执行此操作 List
  • 使用枚举变量切换字符串

    我有一个具有不同值的枚举 并且想要切换字符串变量 现在 我在尝试将枚举值转换为字符串 可以用作大小写常量 时遇到了困难 我最好的尝试是将枚举转换为字符串数组 但开关似乎不接受数组值作为大小写常量 IntelliJ 说 需要恒定的表达 Enu
  • 一起使用 String 和 int 时的 System.out.println 行为 [重复]

    这个问题在这里已经有答案了 考虑下面的代码片段 public class Student public static void main String args int a 3 int b 4 System out println a b
  • 如何在 Struts 2 中访问 OGNL 跟踪评估?

    有人告诉我要优化网络应用程序 为此 我使用JProfiler https www ej technologies com products jprofiler overview html 我注意到很大一部分响应时间都花在了表示层上 特别是当
  • 在 Struts 2 中使用单个文件标签上传多个文件

    我想使用单个 Struts 2 文件标签上传多个文件 就像在 Gmail 中一样 我们使用 CTRL 键来选择多个文件来附加多个文件 我知道如何上传多个文件 但我想使用单个文件标签 我在一个小画廊应用程序中上传多个文件 如果您的操作已设置为
  • 在大画布上滚动

    我需要一些帮助来了解滚动绘制到 Android 画布上的项目的基础知识 假设我想创建一个时间线 其中 0 处的时间是可视化的顶部 并且随着时间的增加 时间线继续呈现在上一个点下方 如果我想在 Android 上渲染它 我知道我可以通过重写
  • 如何使用JSqlParser向sql添加where条件?

    我想用JSqlParser向sql添加where条件 例如 Before select from test table where a 1 group by c After select from test table where a 1
  • 正确的单元测试技术

    在使用 TDD 时 我发现自己需要测试一个包含查找值的常量 最终 哈希图 请查看更新中出现这种情况的原因 见下文 private static final Map
  • 如何找到 JAR:/home/hadoop/contrib/streaming/hadoop-streaming.jar

    我正在练习有关 Amazon EMR 的复数视角视频教程 我被困住了 因为我收到此错误而无法继续 Not a valid JAR home hadoop contrib streaming hadoop streaming jar 请注意
  • 只有创建视图层次结构的原始线程才能触摸其视图。在安卓上[重复]

    这个问题在这里已经有答案了 我只是一个初学者 所以请原谅我问一个可能愚蠢的问题 我不明白只有创建视图层次结构的原始线程才能触摸其视图的含义 请有人告诉我为什么会发生此错误以及如何解决此问题 ThankYou 这是我的班级 public cl

随机推荐

  • 换行CRLF,LF和CR,IntelliJ下设置默认为LF

    在window下开发有一个大坑 就是换行默认是CRLF 但是Linux下只有换行LF 这样代码提交后 会出现编译问题 首先我们先介绍CRLF LF和CR CR是MAC老版本的做法 就是回车 但是后来的MAC系统统一换成LF了 LF是Linu
  • python计算圆周率

    最近一段时间在学习python算法 今天分享5种python计算圆周率的方法 1 割圆法 2 无穷级数法 3 蒙特卡洛法 4 梅钦法 5 拉马努金法 题目来自头歌习题 希望能帮到大家 代码如下 1 割圆法 编程实现割圆法计算圆周率 并输出分
  • excel打开后灰色不显示内容_如何解决EXCEL表格打开显示空白(灰色)的问题

    Excel表格打开没有工作表信息 显示空白 界面是灰色的 大多是单一表格有这种现象 其他表格没有问题 一般是Excel设置问题 方案一 打开故障Excel 视图 窗口 取消隐藏 方案二 在系统左下角开始菜单 找到所有程序 Microsoft
  • es 指定排序字段_ElasticSearch按照指定字段排序

    默认情况下 ES的结果集会按照相关性进行排序 相关性越高 排名越靠前 不过这个规则到了实际应用中往往并不能完全满足我们多变的需求 对于查询结果 除了要找出它们来 还经常需要根据某一规则进行排列 这个规则一般就是指按照某一特定字段排序 按照d
  • Cas5.3服务器集成DM8 达梦数据库

    DM8达梦数据库相关准备 1 安装DM8达梦数据库并安装相关数据库实例 省略一千字 2 新建ucas auth user表 并增加相关用户条记录 DROP TABLE IF EXISTS ucas auth user CREATE TABL
  • 命令行修改java 内存,在命令行上增加jMeter的内存

    I am running jMeter from the command line on a Mac Today it threw an Out of memory heap space error newbie sh jmeter sh
  • PlayerPawn(鼠标控制移动、旋转、大小缩放)

    ue4制作PlayerPawn 鼠标拖动 旋转 YLimtMin 值 89 YLimtMax 值 10 鼠标滚轮键 控制弹簧臂长短 主要控制移动开关 函数LimtMovsePicth
  • STL——map、set等红黑树结构的最后一个元素

    map set等背后由于红黑树的关系 插入元素后便成为 平衡 搜索树了 所以末尾元素默认为最大值 得到该值的方法 1 利用 rbegin 反向迭代器 int main int argc char argv map
  • IntersectionObserver实现小程序长列表优化

    IntersectionObserver实现小程序长列表优化 关于 IntersectionObserver 思路 这里以一屏数据为单位 一个分页的10条数据 最好大于视口高度 监听每一屏数据和视口的相交比例 即用户能不能看到它 只将可视范
  • 接口测试之Jmeter+Ant+Jenkins接口自动化测试平台

    平台简介 一个完整的接口自动化测试平台需要支持接口的自动执行 自动生成测试报告 以及持续集成 Jmeter支持接口的测试 Ant支持自动构建 而Jenkins支持持续集成 所以三者组合在一起可以构成一个功能完善的接口自动化测试平台 环境准备
  • IDEA中输入法无法输入中文

    偶尔而遇到这个问题 又忘记了 记录下 在idea内无法输入中文 win环境可以 很简单快捷键 ctrl shift e 解决问题 看到好多文章去改变量 改配置文件 这
  • LinearLayout加载动态view时显示不全解决办法

    问题 在某个主要Layout里面有个LinearLayout 用来动态加载别的view页面 如果需要加载的动态view内容很空洞 例如没有足够的Text长度来撑起整个layout宽度 这时候这个被加载的view就会不能以fill paren
  • 图像处理入门5-特征提取

    特征提取 图像特征提取属于图像分析的范畴 是对图像信息的深层理解 是数字图像处理的高级阶段 同时也是图像识别的开始 特征工程是图像处理的必备工具 所以掌握它的重要性不言而喻 什么是特征 特征是某一类对象区别于其他类对象的相应 本质 特点或特
  • mybatis-plus的落地实践

    一 mybatis plus官网 MyBatis Plus 二 应用层面 mapper entitty 三 配置 1 引入依赖
  • cv_bridge 冲突(完美解决)

    ubuntu18 04 ros 用 opencv3 2 0 版本 设置 cmake 找到 OpenCVConfig cmake CMakeLists txt 文件里 find package 之前加一行 set set OpenCV DIR
  • 2018.07.20 WorkSummary——04

    今天任务 优化后台代码 简化前端js部分 收获 1 数据库部分表关联与左右连接的分别占用内存的问题 一下面的为例子 SELECT FROM 表a left joint 表b ON 表a bid 表b id LEFT JOIN 表c ON 表
  • 现代控制理论5——稳定性与稳定性判据

    注 本文是在MOOC平台上学习西北工业大学 现代控制理论基础 郭建国 赵斌 郭宗易 的课程进行随笔记录与整理 一 李雅普诺夫稳定性理论 1 前期铺垫 稳定性是系统正常工作的重要特性 稳定性 是描述初始条件 不一定为0 下 系统是否具有收敛性
  • vue实用插件分享

  • 特征学习与特征工程

    特征学习与特征工程 表示学习 当我们学习一个复杂概念时 总想有一条捷径可以化繁为简 机器学习模型也不例外 如果有经过提炼的对于原始数据的更好表达 往往可以使得后续任务事倍功半 这也是表示学习的基本思路 即找到对于原始数据更好的表达 以方便后
  • Java 序列化详解

    Java 序列化 Serialization 是指将一个 Java 对象转换成字节序列 以便在网络上传输或存储在本地磁盘中 而反序列化 Deserialization 则是将已经序列化的字节序列恢复为 Java 对象 Java 提供了自带的