序列化&反序列化

035-安全开发-JavaEE应用&原生反序列化&重写方法&链条分析&触发类&类加载 小迪安全2023笔记 阅读详情

对象序列化

1、对象序列化概述

序列化是一种对象的传输手段,Java有自己的序列化管理机制。对象序列化,就是把一个对象变为二进制的数据流的一种方法,通过对象的序列化可以方便地实现对象的传输或存储,如图 1-1所示。

图 1-1

一个类的实例化对象想被序列化,则对象所在的类必须实现java.io.Serializable接口。然而此接口并没有提供任何的抽象方法,所以该接口只是一个标识接口(只是表示一种对象可以被序列化的能力)。

范例1:定义序列化对象类Student

//实现Serializable接口
public class Student implements Serializable {
    private String name;
    private Integer age;
    private Integer score;

    public Student() {
    }

    public Student(String name, Integer age, Integer score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Integer getScore() {
        return score;
    }

    public void setScore(Integer score) {
        this.score = score;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", score=" + score +
                '}';
    }
}

本程序定义的Student类实现了Serializable接口,所以此类的实例化对象都允许序列化转成二进制进行传输。

tips:对象序列化和对象反序列化操作时的版本兼容问题。

  • 在对象进行序列化或者反序列操作的时候,要考虑JDK版本的问题,如果序列化JDK版本和反序列化JDK版本不统一则有可能造成异常。所以在序列化操作中,引入了一个serialVersionUID的常量,可以通过此常量来验证版本的一致性,即serialVersionUID是序列化前后的唯一标识符。在进行反序列化时,JVM会把传来的字节流中的serialVerionUID与本地相应实体(类)的serialVersionUID进行比较,如果相同就认为一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。
  • 当实现java.io.Serializable接口的实体(类)没有显式地定义一个名为serialVersionUID,类型为long的变量时,Java序列化机制在编译时会根据该类的各方面信息自动产生一个默认的serialVersionUID,一旦更改了类的结构或者信息,则类的serialVersionUID也会跟着改变。
  • 为了serialVersionUID的确定性,写代码时还是建议凡是实现了java.io.Serializable接口的类,最好不要通过编译器来自动生成,人为显式地定义一个名为serialVersionUID,类型为long的变量,那么只要不修改这个变量值的序列化实体都可以相互进行序列化和反序列化。

2、序列化与反序列化处理

序列化和反序列化需要进行二进制存储格式上的统一,为此Java提供了对象序列化操作类。Serializable接口只是定义了某一个类的对象是否被允许序列化,然而对于序列化和反序列化操作的具体实现则需依靠ObjectOutputStream和ObjectInputStream两类完成。这两类的继承结构如图 2-1所示。

图 2-1

ObjectOutputStream类可以将对象转为特定格式的二进制数据输出,常用方法如表 2-1所示;ObjectInputStream类可以读取ObjectOutputStream类输出的二进制对象数据,并将其转为具体类型的对象返回,常用方法如表 2-2所示。

表 2-1
方法类型描述
public ObjectOutputStream(ObjectOutputStream out) throws IOException构造传输输出的对象
public final void writeObject(Object obj) throws IOException普通输出对象
表 2-2
方法类型描述
public ObjectInputStream(InputStream in) throws IOException构造构造输入对象
public final Object readObject() throws IOException, ClassNotFoundException普通从指定位置读取对象

范例2:实现对象序列化和反序列化操作

/*
在Student类中添加两个方法
*/

//1、序列化操作
public static void serialize(Object object, String fileName) throws IOException {
    ObjectOutputStream objectOutputStream = new ObjectOutputStream(
        new FileOutputStream(new File(fileName)));
    objectOutputStream.writeObject(object);
    objectOutputStream.close();

    System.out.println("序列化成功!");
}

//2、反序列化操作
public static Object deserialize(String fileName) throws IOException, ClassNotFoundException {
    ObjectInputStream objectInputStream = new ObjectInputStream(
        new FileInputStream(new File(fileName)));
    Object object = objectInputStream.readObject();
    objectInputStream.close();

    System.out.println("反射序列化成功!");
    return object;
}
//测试类
public class SerializeTestDemo {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Student student = new Student("Chen", 22, 22);
        System.out.println(student);
        //序列化
        Student.serialize(student, "chen.dat");
        System.out.println("==========");

        //反序列化
        Student chen = (Student) Student.deserialize("chen.dat");
        System.out.println(chen);
    }
}

/*
输出结果:
Student{name='Chen', age=22, score=22}
序列化成功!
==========
反射序列化成功!
Student{name='Chen', age=22, score=22}
*/

本程序以二进制文件(chen.dat)作为序列化操作的存储终端 ,在程序中首先通过ObjectOutputStream类将一个Student类的实例化对象输出到文件中,随后再利用ObjectInputStream类将二进制的序列化数据读取并转为Student类实例化对象返回。


3、transient 关键字

默认情况下,当执行对象序列化操作的时候,会将类中的全部属性的内容进行序列化操作,为了保证对象序列化的搞笑传输,就需要防止一些不必要的成员属性的序列化处理。当成员属性不需要进行序列化处理时就可以在属性定义上使用transient关键字来完成。

范例3:transient 关键字的序列化和反序列化操作

//将Student类的score字段定义为transient
private transient Integer score;

//测试类的代码不做任何改变

/*
输出结果:
Student{name='Chen', age=22, score=22}
序列化成功!
==========
反射序列化成功!
Student{name='Chen', age=22, score=null}
*/

本程序对Student类对象进行序列化处理,score属性的内容是不会被保存下来的,这样进行反序列化操作时,score使用的将是其数据类型的默认值。

tips:凡是被static修饰的字段是不会被序列化的。

因为序列化保存的是对象的状态而非类的状态,所以会忽略static静态域。

4、序列化的受控和加强

序列化和反序列化的过程其实是有漏洞的,因为从序列化到反序列化是有中间过程的,如果被人拿到中间字节流,然后加以伪造或者篡改,那么反序列化返回的实例化对象就会有一定的风险了。毕竟反序列化也是相当于一种**“隐式的”对象构造**,因此,我么希望在反序列时,进行受控的对象反序列化操作。

具体的操作就是自行编写readObject()方法,用于对象的反序列化构造,从而提高约束性。既然是自行编写readObject()方法,那就可以做更多的事情:比如说各种判断工作。

还是以上述的Student类说,一般而言,成绩的取值是在0~100之间,我们为了防止学生的成绩在反序列时被别人篡改,我们可以自行编写readObject()方法用于反序列的控制

/*
在Student类中再添加一个个方法
*/
//自行编写readObject()方法用于反序列的控制
private void readObject(ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException {
        //调用默认的反序列方法
        objectInputStream.defaultReadObject();

        //手工检测反序列化后学生成绩的有效性,若发现问题。立即终止操作!
        if (0 > score || 100 < score) {
            throw new IllegalArgumentException("分数只能在0~100之间");
        }
    }
//测试类
public class SerializeTestDemo {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Student student01 = new Student("cbc", 222, 22);
        System.out.println(student01);
        //序列化
        Student.serialize(student01, "cbc.dat");
        //反序列化
        Student cbc = (Student) Student.deserialize("cbc.dat");
        System.out.println(cbc);

        System.out.println("==============================");
        Student student02 = new Student("zhang", 2, 101);
        System.out.println(student02);
        //序列化
        Student.serialize(student02, "zhang.dat");
        //反序列化
        Student zhang = (Student) Student.deserialize("zhang.dat");
        System.out.println(zhang);

    }
}

/*
输出结果:
序列化成功!
反射序列化成功!
Student{name='cbc', age=222, score=22}
==============================
Student{name='zhang', age=2, score=101}
序列化成功!
Exception in thread "main" java.lang.IllegalArgumentException: 分数只能在0~100之间
*/    

对于上面的代码,我一开始也是很懵,怎么自定义为private的readObject()方法也可以被自行调用。后来看到大牛的博客后,看到ObjectStreamClass类最底层的实现,才恍然大悟:又是Java强大的反射机制。如图 4-1。

图 4-1

11-4 AEB 算法原理及系统组成 本专题旨在探讨如何利用仿真软件开发自动紧急制动系统AEB,主要通过整理开发流程,实现从需求到验证的全流程掌握,为后续开发提供支持;同时,研究了如何在汽车自动驾驶仿真工具中开发自己的算法,并解决了从ISO、E-CNAP、GB/T以及交通法规等提炼出功能需求的问题,以快速实现原型模型的开发。本专题重点讲解了AEB的工作原理、系统/软件架构和需求、算法模型及实现、CCRs/CCRb/CCRm建模与仿真、VRU-AEB-B/P/M建模与仿真,同时还提供了测试用例,期待将AEB算法成功地产品化。 阅读详情

相关推荐

玩转Matlab-Simscape(初级)-01-从一个简单模型开始学习之旅

本文从初学者的角度分享的关于Matlab simscape 的基础内容,简单分享了Simscape搭建模型,创建子系统,修改定义参数等内容,为将来深入学习和使用simscape做铺垫。

万金油笑匠的博客 6516

Java中的对象序列化与反序列化:实现与应用

可以通过实现。

微赚淘客开发者博客 1026

Smali语言基础语法

定义、声明、调用 Smali数据类型 定义:与Java相同,Smali中也有一套数据类型体系,且该体系实质上是同Java一一对照的。 示例1:Smali——Java数据类型对照表 PS:如上图所示,Smali语言中的数据类型的关键词基本上为Java中同名数据类型的首字母大写,需要着重记忆的例外为:1.long类型的关键词为大写J;2.boolean类型的关键词为大写Z;3.数组的关键词为左半边中括号[;4.object类型(各种类)的关键词为大写L加上该类的全类名路径,路径中的层级用/分割。

aketoshknight的博客 1万+

学习-Java输入输出之对象IO流之序列化一个对象

任务描述本关任务:序列化给定 Student 对象到给定文件中,再通过反序列化把其转化为一个对象。相关知识之前我们学习了 InputStream(字节输入流)和 OutputStream (字节输出流),下面我们来了解一下它们的子类---ObjectInputStream (对象输入流)和 ObjectOutputStream(对象输出流)。为什么要有对象流有的时候,我们可能需要将内存中的对象持久化到硬盘上(序列化),或者将硬盘中的对象信息读到内存中(反序列化),这个时候我们需要使用对象流。序列化和反序列化

weixin_46075438的博客 2538

模电(十四)差分放大电路

目录 差分放大电路 双端输入双端输出 Q点分析 抑制共模信号 放大差模信号 双端输入单端输出 Q点分析 差模信号分析 共模信号分析 单端输入双端输出 单端输入单端输出 四种接法比较 具有恒流源的差分放大电路 差分放大电路的改进 差分放大电路 采用引入支流负反馈,温度补偿来克服零点漂移(温度变化,直流电源波动,元器件老化产生的输入电压为零,输出电压不为零的...

weixin_43674847的博客 2万+

ESP32-S3开发环境避坑指南:VS Code+ESP-IDF离线安装全流程(附国内镜像加速)

本文提供了一份详细的ESP32-S3开发环境离线安装指南,重点解决网络依赖问题。通过整合国内镜像加速,手把手教你完成VS Code、ESP-IDF框架、工具链及Python依赖的本地化部署,实现稳定、可重复的开发环境搭建,大幅提升IoT开发效率。

peach的博客 961

序列化与反序列化的实现

对象序列化将对象转换为二进制字节流的形式,将内存中的对象输出到本地磁盘的文件中1、自定义类Window并实现Serializable接口2、创建文件对象3、创建文件输出流对象用于给文件中输出二进制字节信息4、对文件输出流进行封装,将其变为对象输出流5、将序列化之后的二进制字节流写入到文件中文本文件中的内容如下。

qq_52391639的博客 219

华为FusionCharge 720kW液冷直流快充桩主电流全路径深度详解

本文档详细介绍了华为FusionCharge 720kW液冷分体式直流充电系统的主电流路径全链路解析,适用于配套DS720-720LCNA1充电主机及DT600L1-CNA1液冷终端、DT250N2-CNA1自然冷终端的运维工作。内容涵盖从电网交流输入到电动汽车充电的全过程,重点解析交流门、整流正门、主控正门等五大柜门区域的核心元器件分布及功能,包括额定参数、安全规范、故障排查等关键运维知识。操作人员需持有高压电工证并通过专项培训,作业时必须严格遵守断电验电、穿戴PPE防护装备等安全红线。文档通过16个关键

2401_84939870的博客 745

练习-Java输入输出之对象IO流之序列化数组

任务描述本关任务:序列化给定 Student 数组到给定文件中,再通过反序列化把其转化为 Student 数组。编程要求仔细阅读右侧编辑区内给出的代码框架及注释,在 Begin-End 间编写程序代码,序列化 Student 数组到给定文件中,再通过反序列化把其转化为 Student 数组,具体要求如下:Student 类代码如下:

weixin_46075438的博客 2608

S32DS新建工程、编译调试下载、导入工程详细介绍

新建了一个工程之后,下面简单介绍下基本的UI界面。其中最左下角那个是界面,这个界面很重要,是图形化配置界面,然后可以根据这些配置自动生成代码。其中,左边那些配置文件,都是系统帮我们创建好了的,我们其实可以直接用就行。有PE工具的调试,以及Jlink工具的调试。我目前使用到PE工具调试可以查看寄存器值,而Jlink调试查看不了寄存器值。连接了开发板之后,点击Debug就可以吧程序下载到芯片上了,而且可以进入到调试界面。

luobeihai的博客 2万+

R语言pls包实战:手把手教你用偏最小二乘(PLS)搞定高维数据回归(附完整代码与数据标准化避坑指南)

本文详细介绍了如何使用R语言的pls包进行偏最小二乘(PLS)回归分析,特别针对高维数据回归问题。通过完整的代码示例和数据标准化避坑指南,帮助读者掌握从数据预处理到模型优化的全流程,解决实际应用中的常见问题。

weixin_42662605的博客 350

C# 序列化&反序列化

c# 序列化和反序列化的应用场景,序列化和反序列化的三种方式带例子

weixin_43925768的博客 2331

Vue2 - 最新详细实现接入天地图详细配置流程及示例代码教程,提供获取用户当前定位的城市名称及省市区数据、精准经纬度信息、IP属地定位、地图搜索标点等示例,解决天地图跨域报错/页面白屏/定位不准问题

vue2,nuxt2,天地图,使用教程,vue接入国家天地图,定位api,ip属地定位,获取用户当前位置数据,省市区,地图不显示,白屏,报错,vue2如何使用天地图,地图选点,cors跨域,白名单设置了还是不行,vue项目调用天地图api实现定位,Vue2中使用天地图,详细教程,天地图申请密钥key教程,经纬度,经纬度不准确,一直定位北京,定位在北京不准怎么办,nuxt项目天地图,网站,网页,h5页面,地图显示不全,获取当前定位,如何使用天地图,拿到客户ip地址定位城市名称,距离计算,实时搜索地址逆解析,天

🏆 前端领域优质创作者 5324

Python&Java之序列化&反序列化

首先什么叫序列化和反序列化? 序列化:将对象转化为字节的过程。 反序列化:将字节/文件转为对象过程。 作用: 这样可以永久存储,文件,数据库,远程传输,你不可能把内存传输或者保存的吧? Java序列化: Java想要对类实现序列化,首先要实现一个接口(Serializable),不然会报错哦。 序列化首先要有这个对象(这个对象已经被实例化了),我们这里new了一个学术类 Stud...

qq_34939975的博客 1929

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

PHP反序列化&原生类&字符串逃逸&框架反序列化利用

序列化的原因:为了的一个情况(类似于要发送一个椅子快递,不可能整个椅子打包发送,这是非常不方便的,所以就要对椅子进行序列化处理,让椅子分成很多部分在一起打包发送,到目的后重新组装,也就是反序列化处理)序列化:对象转换为数组或字符串等格式反序列化:将数组或字符串等格式转换成对象在php中,serialize()函数是序列化函数、unserialize()函数是反序列化函数上图可见,代码执行完后第一行是被序列化后的字符串。

weixin_67289581的博客 1409

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

一文解决序列化&反序列化体系

序列化是将对象的状态信息转换为可以存储或传输的形式的过程。在Java中,这通常意味着将一个对象(通常是一个实现了接口的类的实例)转换成一系列字节,这些字节可以被保存到文件中或通过网络发送到另一个位置。这样做的目的主要是实现两个目标:持久化存储:通过序列化,对象可以被永久地保存到存储介质(如硬盘)上,即使程序结束运行,对象的状态也可以被保存下来,并在需要时重新加载。网络传输:序列化后的字节流可以通过网络发送给其他计算机,实现对象在不同计算机之间的共享。总结:将数据结构或对象转换成二进制字节流的过程。

zhouhengzhe的博客 2171

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Linux网络:序列化 & 反序列化

讲解Linux的序列化与反序列化,以及jsoncpp库

博客网站 https://async-area.com 1325

Java 序列化&反序列化基础

序列化和反序列化 简述: Java序列化是指把Java对象转换为字节序列的过程,即把一个对象变为二进制的数据流的一种方法,通过序列化可以方便地实现对象的传输和存储;Java反序列化是指把字节序列恢复为Java对象的过程。 student.java: package com.wu.Bean; import java.io.Serializable; public class Student implements Serializable{ private static final long serial

一夜星尘 9346

json序列化 & 反序列化

json序列化:   json的dumps方法可以将json格式数据序列为python的相关数据类型,比如str,常用于打印,另外,在序列化时,中文汉字被转换为unicode编码,在dumps函数中添加参数ensure_ascii=False可解决;dumps的indent参考可以调整显示格式,即缩进,一般设置为2。 json反序列化:   json的loads方法可以把py...

akb7208的博客 148

Java安全—原生反序列化&重写方法&链条分析&触发类

虽然今天的内容看起来有点复杂,但总结起来就一件事,想办法调用其它的readObject,而不是去调用原本的readObject。最后还是要声明一下,以上仅为个人的拙见,如何有不对的地方,欢迎各位师傅指正与补充,有兴趣的师傅可以一起交流学习。

2301_76227305的博客 1309

[Web 安全] PHP 反序列化漏洞 —— PHP 序列化 & 反序列化

这就是前面介绍的反序列化的一个特性 “反序列化生成的对象成员属性值由被反序列化的字符串决定,与原来类预定义的值无关。这样,但其实类名两边其实还藏了两个 ASCII 码值为 0 的字符,所以其真实格式为(URL 编码后的哈,不编码的话 ASCII 值为 0 的其实是不可见字符)类的序列化结果基本大差不差,但是不同 “访问类型” 的变量序列化的结果有很大差异,这部分笔者就按照 “访问类型” 进行分类,并对每个单独进行讲解。如上,可以看到,通过反序列化被保存的值,我们成功还原了用户笔记里写的东西。

Blue17 の 小窝 1345

.NET 中的序列化 & 反序列化

序列化:将对象的状态信息及类型信息,转换为一种易于传输或存储形式(流,即字节序列)的过程。 下图为序列化过程图示,图片来自微软官方文档: 反序列化:与序列化相反,将流转换为对象的过程。 常用的有二进制序列化、XML序列化及JSON序列化三种序列化方式。.NET自身提供了对二进制序列化与XML序列化的支持。我们可以借助第三方库,如Newtonsoft.Json,来实现JSON序列化。 二...

weixin_30426065的博客 164

Java 序列化 & 反序列化

内容是关于Java序列化面试知识。需要提炼核心要点。摘要应简洁,涵盖主要概念、关键点、注意事项。

2302_79978582的博客 614
上一篇: Java虚拟机加载Java类的过程
下一篇: AutoCloseable接口
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

窝在角落里学习

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值