JAVA序列化和反序列化的底层实现原理解析 更新时间:2019年11月27日 14:38:39 作者:myseries 这篇文章主要介绍了JAVA序列化和反序列化的底层实现原理解析,文中通

一、基本概念

1、什么是序列化和反序列化

(1)Java序列化是指把Java对象转换为字节序列的过程,而Java反序列化是指把字节序列恢复为Java对象的过程;

(2)序列化:对象序列化的最主要的用处就是在传递和保存对象的时候,保证对象的完整性和可传递性。序列化是把对象转换成有序字节流,以便在网络上传输或者保存在本地文件中。序列化后的字节流保存了Java对象的状态以及相关的描述信息。序列化机制的核心作用就是对象状态的保存与重建。

(3)反序列化:客户端从文件中或网络上获得序列化后的对象字节流后,根据字节流中所保存的对象状态及描述信息,通过反序列化重建对象。

(4)本质上讲,序列化就是把实体对象状态按照一定的格式写入到有序字节流,反序列化就是从有序字节流重建对象,恢复对象状态。

2、为什么需要序列化与反序列化

我们知道,当两个进程进行远程通信时,可以相互发送各种类型的数据,包括文本、图片、音频、视频等, 而这些数据都会以二进制序列的形式在网络上传送。

那么当两个Java进程进行通信时,能否实现进程间的对象传送呢?答案是可以的!如何做到呢?这就需要Java序列化与反序列化了!

换句话说,一方面,发送方需要把这个Java对象转换为字节序列,然后在网络上传送;另一方面,接收方需要从字节序列中恢复出Java对象。

当我们明晰了为什么需要Java序列化和反序列化后,我们很自然地会想Java序列化的好处。其好处一是实现了数据的持久化,通过序列化可以把数据永久地保存到硬盘上(通常存放在文件里),二是,利用序列化实现远程通信,即在网络上传送对象的字节序列。

总的来说可以归结为以下几点:

(1)永久性保存对象,保存对象的字节序列到本地文件或者数据库中;

(2)通过序列化以字节流的形式使对象在网络中进行传递和接收;

(3)通过序列化在进程间传递对象;

3、序列化算法一般会按步骤做如下事情:

(1)将对象实例相关的类元数据输出。

(2)递归地输出类的超类描述直到不再有超类。

(3)类元数据完了以后,开始从最顶层的超类开始输出对象实例的实际数据值。

(4)从上至下递归输出实例的数据

二、Java如何实现序列化和反序列化

1、JDK类库中序列化和反序列化API

(1)java.io.ObjectOutputStream:表示对象输出流;

它的writeObject(Object obj)方法可以对参数指定的obj对象进行序列化,把得到的字节序列写到一个目标输出流中;

(2)java.io.ObjectInputStream:表示对象输入流;

它的readObject()方法源输入流中读取字节序列,再把它们反序列化成为一个对象,并将其返回;

2、实现序列化的要求

只有实现了Serializable或Externalizable接口的类的对象才能被序列化,否则抛出异常!

3、实现Java对象序列化与反序列化的方法

假定一个User类,它的对象需要序列化,可以有如下三种方法:

(1)若User类仅仅实现了Serializable接口,则可以按照以下方式进行序列化和反序列化

  • ObjectOutputStream采用默认的序列化方式,对User对象的非transient的实例变量进行序列化。
  • ObjcetInputStream采用默认的反序列化方式,对对User对象的非transient的实例变量进行反序列化。

(2)若User类仅仅实现了Serializable接口,并且还定义了readObject(ObjectInputStream in)和writeObject(ObjectOutputSteam out),则采用以下方式进行序列化与反序列化。

  • ObjectOutputStream调用User对象的writeObject(ObjectOutputStream out)的方法进行序列化。
  • ObjectInputStream会调用User对象的readObject(ObjectInputStream in)的方法进行反序列化。

(3)若User类实现了Externalnalizable接口,且User类必须实现readExternal(ObjectInput in)和writeExternal(ObjectOutput out)方法,则按照以下方式进行序列化与反序列化。

  • ObjectOutputStream调用User对象的writeExternal(ObjectOutput out))的方法进行序列化。
  • ObjectInputStream会调用User对象的readExternal(ObjectInput in)的方法进行反序列化。

4、JDK类库中序列化的步骤

步骤一:创建一个对象输出流,它可以包装一个其它类型的目标输出流,如文件输出流:

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(``"D:\\object.out"``));

步骤二:通过对象输出流的writeObject()方法写对象:

oos.writeObject(new User(``"xuliugen"``, ``"123456"``, ``"male"``));

5、JDK类库中反序列化的步骤

步骤一:创建一个对象输入流,它可以包装一个其它类型输入流,如文件输入流:

ObjectInputStream ois= new ObjectInputStream(new FileInputStream(``"object.out"``));

步骤二:通过对象输出流的readObject()方法读取对象:

User user = (User) ois.readObject();

说明:为了正确读取数据,完成反序列化,必须保证向对象输出流写对象的顺序与从对象输入流中读对象的顺序一致。

6、序列化和反序列化的示例

为了更好地理解Java序列化与反序列化,举一个简单的示例如下:

public class SerialDemo {public static void main(String[] args) throws IOException, ClassNotFoundException {//序列化FileOutputStream fos = new FileOutputStream("object.out");ObjectOutputStream oos = new ObjectOutputStream(fos);User user1 = new User("xuliugen", "123456", "male");oos.writeObject(user1);oos.flush();oos.close();//反序列化FileInputStream fis = new FileInputStream("object.out");ObjectInputStream ois = new ObjectInputStream(fis);User user2 = (User) ois.readObject();System.out.println(user2.getUserName()+ " " + user2.getPassword() + " " + user2.getSex());//反序列化的输出结果为:xuliugen 123456 male}
}public class User implements Serializable {private String userName;private String password;private String sex;//全参构造方法、get和set方法省略
}

object.out文件如下(使用UltraEdit打开):

img

注:上图中0000000h-000000c0h表示行号;0-f表示列;行后面的文字表示对这行16进制的解释;对上述字节码所表述的内容感兴趣的可以对照相关的资料,查阅一下每一个字符代表的含义,这里不在探讨!

类似于我们Java代码编译之后的.class文件,每一个字符都代表一定的含义。序列化和反序列化的过程就是生成和解析上述字符的过程!

序列化图示:

img

反序列化图示:

img

三、相关注意事项

1、序列化时,只对对象的状态进行保存,而不管对象的方法;

2、当一个父类实现序列化,子类自动实现序列化,不需要显式实现Serializable接口;

3、当一个对象的实例变量引用其他对象,序列化该对象时也把引用对象进行序列化;

4、并非所有的对象都可以序列化,至于为什么不可以,有很多原因了,比如:

安全方面的原因,比如一个对象拥有private,public等field,对于一个要传输的对象,比如写到文件,或者进行RMI传输等等,在序列化进行传输的过程中,这个对象的private等域是不受保护的;

资源分配方面的原因,比如socket,thread类,如果可以序列化,进行传输或者保存,也无法对他们进行重新的资源分配,而且,也是没有必要这样实现;

5、声明为static和transient类型的成员数据不能被序列化。因为static代表类的状态,transient代表对象的临时数据。

6、序列化运行时使用一个称为 serialVersionUID 的版本号与每个可序列化类相关联,该序列号在反序列化过程中用于验证序列化对象的发送者和接收者是否为该对象加载了与序列化兼容的类。为它赋予明确的值。显式地定义serialVersionUID有两种用途:

在某些场合,希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有相同的serialVersionUID;

在某些场合,不希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有不同的serialVersionUID。

7、Java有很多基础类已经实现了serializable接口,比如String,Vector等。但是也有一些没有实现serializable接口的;

8、如果一个对象的成员变量是一个对象,那么这个对象的数据成员也会被保存!这是能用序列化解决深拷贝的重要原因;

四、反序列化漏洞

相关反序列化漏洞可以查阅相关资料,这里不介绍了。

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

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

相关文章

笔记本电脑重启快捷键是什么

品牌型号:联想小新Air-14 2020 系统:win10 1909 64位企业版 部分用户可能电脑型号不一样,但系统版本一致都适合该方法。 用电脑用久了的朋友们都知道电脑的快捷键在哪里,笔记本电脑重启快捷键是什么?下面就给大家分享一下笔记…

新手iso系统怎么安装 新手安装iso镜像文件详细步骤

操作系统大多是iso格式的文件,尤其是Windows系统,都是.iso镜像,如果电脑可以正常使用,iso镜像文件只需解压出来就可以安装,但是对于新手来说,可能解压iso系统都是个问题,那么新手iso系统怎么安装…

Java获取一天的起止时间(Java8写法使用 LocalDateTime)

Calendar calendar new GregorianCalendar();// 0可以修改,0代表当前时间,-1代表前一天calendar.add(Calendar.DAY_OF_MONTH,0);//一天的开始时间 yyyy:MM:dd 00:00:00calendar.set(Calendar.HOUR_OF_DAY,0);calendar.set(Calendar.MINUTE,0);calend…

Windows10系统以太网显示“未识别的网络”如何解决

如果你的Win10系统电脑连不上网,那么可能会是三种情况导致的:受限未识别网络、拨号不成功或者网线没插好。其中,本地连接(以太网)提示“未识别的网络”情况是我们最经常碰到的。如果你的Win10系统无法访问网络,且在有线连接路由器…

如何在bios里调节风扇转速 bios设置风扇转速的方法

CPU的温度对电脑的正常运行有很大的影响,如果温度过高那么电脑就不能正常工作,风扇在降低温度中发挥着很大的作用,那么如何在bios里调节风扇转速呢?下面就给大家分享bios设置风扇转速的方法。 1、启动电脑按快捷键进入BIOS里面,…

win7开机黑屏怎么解决?win7开机黑屏出现reboot and select的解决方法

很多用户有遇见电脑黑屏的情况,而且还出现 reboot and select proper boot deviceor insert boot media in selected boot device 的提示,win7开机黑屏怎么解决呢?可能是硬盘接口数据线出现松动了,也可能是硬盘坏了。今天小编整理了相关的教…

win10系统进入监护人模式的方法

现在很多的小学生也会一直玩电脑很多家长就担心影响孩子学习因此想要设置监护人模式但是不知道win10系统监护人模式怎么进入,今天就给你们带来了win10系统进入监护人模式的方法,快来看看吧。 win10系统进入监护人模式的方法: 1、首先点击左…

解决win10电脑声音太小的问题

右击任务栏声音图标,点击选择菜单中的“播放设备”。 如果声音图标未显示,请在控制面板(大图标查看方式)中,点击选择“声音”。 在声音对话框,点击选中扬声器,然后点击下面的“属性”。 在扬声器 属性对话框&#xff0…

win7 ie临时文件夹怎么修改存放位置

首先,鼠标左键双击打开Internet Explorer,然后点击右上角的设置图标,点Internet选项。 打开之后,找到并点击“设置” 打开之后,找到并点击“移动文件夹” 然后找一个存放IE临时文件的位置,设好了之后点确定。 要让IE临时文件的移动生效,要对移…

笔记本蓝牙怎么打开

笔记本蓝牙有什么用呢?我们可以用蓝牙耳机连接上笔记本的蓝牙,然后就可以听音乐,看电影等操作。所以接下来就来给小伙伴说说怎么打开笔记本蓝牙。 以win8为例进行演示 1、首先,把鼠标拉倒最右下角,然后点设置。 2、然后&#x…

Java8时间间隔计算Period.between与LocalDate.until区别LocalDate,LocalDateTime计算两个时间的相差时间

记录一线上问题,编辑会员卡信息,有效期截止时间由2022-04-17修改为2023-04-18,操作成功之后显示剩余的有效天数为24天,实际上怎么也得有三百多天.之前本地测试一直没有问题,现将定位过程记录一下. 本地复测之后发现计算的是24天,果然有问题. Period period Period.between(Loc…

win8升级win10出现错误代码1049怎么回事

最近有用户把自己的win8系统升级到win10后遇到了错误代码1049,那么这是咋回事呢?下面小编就给大家介绍一下win8升级win10出现错误代码1049的解决方法。 1、报错信息如下所示,完全不理解是什么意思,点击《转到存储》菜单,看到的是…

简单几步解决笔记本风扇一直嗡嗡响的问题

我们在使用电脑时难免会遇到一些问题。例如我们都知道笔记本都会自带有一个风扇,如果长时间使用的话就会帮助扇热。但最近有网友就表示自己的笔记本风扇一直嗡嗡响,不知道怎么回事,也不知道该如何解决很是苦恼,所以今天小编为大家…

acer笔记本电脑如何进入bios设置

acer笔记本电脑对于外出办公的用户来说是一个不错的选择,但最近小编发现有许多使用acer笔记本电脑的朋友是不知道怎么进入BIOS设置的。因此,针对这个问题我就赶紧整理了这个acer笔记本电脑进入BIOS设置的教程,现在就来分享给大家,…

[内排序]八大经典排序合集

文章目录1 排序的基本概念1.1 什么是排序1.2 排序的稳定性1.3 内排序和外排序2 插入排序2.1 直接插入排序1. 排序思路2. 直接插入排序实例3. 排序算法4. 算法分析5. 折半插入排序 / 二分插入排序5.1 排序思路5.2 排序算法5.3 算法分析2.2 希尔排序1. 排序思路2. 希尔排序实例3.…

怎么解决机械革命笔记本蓝屏问题

1、重启电脑,出现logo界面后连续按F2键直到打开bios,接着切换至“Advanced”,将光标移至“OS Support”选项,并将后面数值调成“Others”。 2、接下来将光标移至“SATA Device”选项,将硬盘模式调成“AHCI”。 3、最后…

bootsqm.dat是什么文件 bootsqm.dat可以删除吗

我们经常会发现系统C盘里面有一个bootsqm.dat文件,这个文件占用空间还是蛮大的,因此有些用户想要知道bootsqm.dat是什么文件?bootsqm.dat可以删除吗?其实这两个问题很简单,下面就由小编来告诉大家bootsqm.dat是什么文件及其能不能删除吧! …

win10笔记本打开只有飞行模式的解决方法

方法一: 1、按下“winr”打开运行,输入“regedit”,依次展开到“HKEY_LOCAL_MACHINESYSTEMCurrentControlSetservicesNdisuio”,查看其“DisplayName”键值是“NDISUsermode I/O Protocol”如缺损,可新建; 2、在右边…

笔记本win10系统连接wifi显示无Internet安全如何解决

方法一: 1、进入设置,找到“网络和Internet”,双击; 2、找到“更改适配器选项”,双击; 3、双击进入你的WLAN; 4、找到页面下方“属性”,单击; 5、(1)如果在项目列表里出项“WifiMasterNATDriver”是选中状态的话&…

win10 更新后不能切换输入法怎么办 win10输入法切换不了怎么解决

有win10用户说他在更新完系统后,在切换输入法的时候发现竟然切换不了无法切换,都不知道该怎么办了,这个小问题也是常有的,那么win10更新后不能切换输入法怎么办呢,下面小编给大家分享win10输入法切换不了的解决方法。 …