JAVA序列化和反序列化学习笔记

news/2024/4/26 4:00:18/文章来源:https://blog.csdn.net/snowlyzz/article/details/127617904

0x01

开始学习JAVA反序列化,参考 《安全漫谈》和feng师傅的文章一步一步来,希望 能赶在这个学期学完java最基础的东西, 笔记做到这里方便自己查阅,也是事先实操了一下 ,才写的笔记

概念:

JAVA 序列化 就是把一个 JAVA Object 变成一个二进制字节数组 即 byte[]

JAVA 反序列化 就是把一个 二进制数组 byte[] 变回Java 对象 ,即JAva Object

序列化/反序列化具备条件

如果一个类 实现序列化或反序列化操作, 必须要实现 Serializable接口或者Externalizable接口。 最好还要有一个  serialVersionUID 属性

这属性的介绍:

每个可序列化的类在序列化时都会关联一个版本号 , 这个版本号就是 serialVersionUID 属性 .

在反序列化过程中会根据这个版本号来判断序列化对象的发送者和接收着是否有与该序列化/反序列化过程兼容的类 .( 简单的说就是序列化过程和反序列化过程都需要被序列化的类 , 通过 serialVersionUID 属性来判断这两个类的版本是否相同 , 是否是同一个类 ) . 如果不相同 , 则会抛出 InvalidClassException 异常

serialVersionUID 属性必须通过 static final long 修饰符来修饰 .

如果可序列化的类未声明 serialVersionUID 属性 , 则 Java 序列化时会根据类的各种信息来计算默认的 serialVersionUID 值 . 但是 Oracle 官方文档强烈建议所有可序列化的类都显示声明 serialVersionUID 值 .

Serializable

只是一个空接口,没有任何操作

 只是一个标识接口,意味着实现了这个接口的类 可以进行序列化和反序列化操作。

Externalizable

 继承的 Serializable接口的接口

Externalizable 接口使用较为麻烦,一般会使用Serializable

 ObjectOutputStream

官方文档:

关键是 writeObject 方法 ,可以将对象写入数据流中(序列化) 

需要注意的是 

对象的默认序列化机制会写入对象的类,类签名以及所有非瞬态和非静态字段的值。 对其他对象的引用(瞬态或静态字段除外)也会导致这些对象被写入。 

需要注意的是,static 字段是不会被序列化的,只会保留原有的值(个人理解

关于类签名:

在开发 JNI( Java Native Interface , Java 本地接口 ) 时需要调用 Java 层的方法或创建引用 , 此时就会用到 Java 签名机制 . 比如基本数据类型的签名如下所示:

 https://www.jianshu.com/p/a1438b476e82

ObjectInputStream

而这个函数,则是 php中的 unserialize , 反序列化。

代码实现:

写三个类进行 实现操作,直接借用feng师傅的代码了,因为我已经测试过了

序列化操作

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;public class Serialize {public static void main(String[] args) throws IOException {flag flag = new flag();flag.setTrueFlag("flag{hello,world}");flag.setTestName("feng");FileOutputStream fout = new FileOutputStream("2.txt");ObjectOutputStream oout = new ObjectOutputStream(fout);oout.writeObject(flag);fout.close();oout.close();}
}

反序列化操作

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;public class unserialize {public class TestUnser2 {public static void main(String[] args) throws IOException, ClassNotFoundException {FileInputStream fin = new FileInputStream("2.txt");ObjectInputStream oin = new ObjectInputStream(fin);flag flag = (flag) oin.readObject();fin.close();oin.close();String trueFlag = flag.getFlag("feng");System.out.println(trueFlag);System.out.println(flag.serialVersionUID);System.out.println(flag.testName);}}
}

flag

package com.summer.unserialize;import java.io.Serializable;public class Flag implements Serializable {static final long serialVersionUID = 1L;private String trueFlag;public static String testName = "test";public void setTestName(String testName){Flag.testName = testName;}public void setTrueFlag(String trueFlag){this.trueFlag = trueFlag;}public String getFlag(String name){System.out.println(name + " get the flag");return this.trueFlag;}
}

代码的具体流程 是 把值写进去,然后序列化成2.txt ,代码实现很简单,但是要注意的地方是这个静态方法 static。

public static String testName = "test";

序列化的时候 传参:

flag.setTestName("feng");System.out.println(flag.testName);

然后我们进行反序列读取看看

看到这里  最后一行的输出值是test ,也就是说 静态的字段不会被序列化,因为反序列化读取后 testName的值还是 test

implement方法

跟着feng师傅思路回到Serializable接口的文档注释里的这个:

 * Classes that require special handling during the serialization and* deserialization process must implement special methods with these exact* signatures:** <PRE>* private void writeObject(java.io.ObjectOutputStream out)*     throws IOException* private void readObject(java.io.ObjectInputStream in)*     throws IOException, ClassNotFoundException;* private void readObjectNoData()*     throws ObjectStreamException;* </PRE>

如果需要特殊的处理,类需要自己 implement 这些方法。

readObject

 总结一下就是,readObject支持我们重写该方法,在该方法中添加新的功能,但是重写的话唯一的限制 就要添加原有的功能,即 defaultReadObject() 方法。

例子:

在flag类中添加

    private void readObject(java.io.ObjectInputStream stream)throws IOException, ClassNotFoundException{stream.defaultReadObject();Runtime.getRuntime().exec("calc");}

然后序列化,再进行反序列化,在反序列化中,会调用

flag flag = (flag) oin.readObject();

而flag中的readObject(),进行重写了,也就实现了反序列化弹出计算器

writeObject

看看 writeObject 的用处。把 Flag 类里面写这个:

    private void readObject(java.io.ObjectInputStream stream)throws IOException, ClassNotFoundException{stream.defaultReadObject();Runtime.getRuntime().exec("calc");System.out.println(stream.readObject());}private void writeObject(java.io.ObjectOutputStream stream)throws IOException{stream.defaultWriteObject();stream.writeObject("This is feng");}

feng师傅有一样的疑惑,为什么把flag 对象写进了流,writeObject方法里又调用了stream.writeObject("This is feng");写了个对象进去,这不就相当于写了两个对象吗?

readObject里面新加的System.out.println(stream.readObject());,又能干什么?

工具查看

STREAM_MAGIC - 0xac ed
STREAM_VERSION - 0x00 05
ContentsTC_OBJECT - 0x73TC_CLASSDESC - 0x72classNameLength - 27 - 0x00 1bValue - com.summer.unserialize.Flag - 0x636f6d2e73756d6d65722e756e73657269616c697a652e466c6167serialVersionUID - 0x00 00 00 00 00 00 00 01newHandle 0x00 7e 00 00classDescFlags - 0x03 - SC_WRITE_METHOD | SC_SERIALIZABLEfieldCount - 1 - 0x00 01Fields0:Object - L - 0x4cfieldNameLength - 8 - 0x00 08Value - trueFlag - 0x74727565466c6167className1TC_STRING - 0x74newHandle 0x00 7e 00 01Length - 18 - 0x00 12Value - Ljava/lang/String; - 0x4c6a6176612f6c616e672f537472696e673bclassAnnotationsTC_ENDBLOCKDATA - 0x78superClassDescTC_NULL - 0x70newHandle 0x00 7e 00 02classdatacom.summer.unserialize.FlagvaluestrueFlag(object)TC_STRING - 0x74newHandle 0x00 7e 00 03Length - 17 - 0x00 11Value - flag{hello,world} - 0x666c61677b68656c6c6f2c776f726c647dobjectAnnotationTC_STRING - 0x74newHandle 0x00 7e 00 04Length - 12 - 0x00 0cValue - This is feng - 0x546869732069732066656e67TC_ENDBLOCKDATA - 0x78

看到objectAnnotation

        objectAnnotationTC_STRING - 0x74newHandle 0x00 7e 00 04Length - 12 - 0x00 0cValue - This is feng - 0x546869732069732066656e67TC_ENDBLOCKDATA - 0x78

stream.writeObject("This is feng");

反序列化结果 

总结

因此可以看出,在自定义的writeobject中 调用传入的ObjectOutputStreamwriteObject方法写入的对象,会写入到objectAnnotation中。

而自定义的readObject 方法中,调入传入的ObjectInputStreamreadObject方法读入的对象,则是objectAnnotation中存储的对象。

rethink

才刚刚入门 感觉还是好难,JAVA漫谈的URLDNS 也跟不上。都是涉及底层的代码。以后再说把呜呜呜

参考

Java 序列化和反序列化 学习笔记_bfengj的博客-CSDN博客

https://www.liaoxuefeng.com/wiki/1252599548343744/1298366845681698

https://blog.csdn.net/dan15188387481/article/details/49977421

https://www.lagou.com/lgeduarticle/94091.html

https://docs.oracle.com/javase/8/docs/platform/serialization/spec/protocol.html

https://www.anquanke.com/post/id/238480
 

 

 

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

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

相关文章

program arguments,vm arguments,environment variable

作者:david_zhang@sh 【转载时请以超链接形式标明文章】 https://www.cnblogs.com/david-zhang-index/p/16846493.html 参数太多,傻傻分不清楚,简单说 1,program arguments是main函数args[]参数 2,vm arguments是java环境变量 3,environment variable是jvm环境变量 看代码…

华为设备配置NAT原理与示例

网络地址转换NAT 文章目录网络地址转换NAT1 NAT概述1.1 NAT产生的技术背景1.2 私有IP地址1.3 NAT技术原理2 静态NAT2.1 静态NAT原理2.2 静态NAT转换示例2.3 静态NAT配置介绍2.4 静态NAT配置示例3 动态NAT3.1 动态NAT原理3.2 动态NAT转换示例3.3 动态NAT配置介绍3.4 动态NAT配置…

resultMap结果映射

文章目录一、resulrMap结果映射二、驼峰命名自动映射查询结果的列名和Java对象的属性名对应不上怎么办&#xff1f; *第一种方式&#xff1a;as给列名起别名 *第二种方式&#xff1a;使用resultMap进行结果映射 *第三种方式&#xff1a;是否开启驼峰命名自动映射&#xff08;配…

算法学习:动态规划

14天阅读挑战赛 努力是为了不平庸~ 系列文章目录 第一章 算法简介 第二章 贪心算法 第三章 分治法 第四章 动态规划 目录系列文章目录2.0兔子序列2.1动态规划基础2.2最长的公共子序列2.2.1问题描述&#xff1a;2.2.2分析问题&设计思路&#xff1a;2.2.3图解思路&#xff1…

Python抓取我的CSDN粉丝数,白嫖GithubAction自动抓取

《Python抓取我的CSDN粉丝数&#xff0c;白嫖GithubAction自动抓取》 一.介绍 这段时间我想申请CSDN的博客专家认证&#xff0c;但是我发现我的总访问量不够&#xff08;博客专家的总访问量要大于20万&#xff09;&#xff0c;所以我就想把我的CSDN每天的 【总访问量】&#…

芯片与自动驾驶技术漫谈

芯片与自动驾驶技术漫谈 从芯片到系统国产,信创产业如何4步走上自主路? 信创产业发展是国家经济数字化转型、提升产业链发展的关键。我国明确了“数字中国”建设战略,抢占数字经济产业链制高点。推进信创产业的发展,促进信创产业在区域性落地生根,带动传统IT信息产业转型,…

【光通信】常见光模块与光纤收发器说明及作用区别

&#xff1a;单纤收发器是指采用的是单模光缆 单纤收发器是只用一根芯&#xff0c;两端都接这根芯&#xff0c;两端的收发器采用不同的光波长&#xff0c;所以能在一根芯里传输光信号。 双纤收发器就是采用了两根芯&#xff0c;一根发送一根接收&#xff0c;一端是发的另一端就…

MongoDB 分片集群均衡器导致的性能下降

近期&#xff0c;有人反馈其mongodb分片集群&#xff0c;在加载处理大批量数据时&#xff0c;程序处理十分缓慢并且应用还会报错&#xff1a;version mismatch detected for 。现将分析汇总如下备用。 一、问题现象 负责同事反馈9月1日18:52分左右&#xff0c;应用报错version…

计算机毕业设计(附源码)python医院预约挂号管理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

学习笔记-php伪协议

伪协议 相关文章 & Source & Reference PHP伪协议的妙用 filter协议 php://filter 是一种元封装器&#xff0c; 设计用于数据流打开时的筛选过滤应用。这对于一体式(all-in-one)的文件函数非常有用&#xff0c;类似 readfile()、 file() 和 file_get_contents()&#x…

网课查题系统搭建-查题校园题库

网课查题系统搭建-查题校园题库 本平台优点&#xff1a; 多题库查题、独立后台、响应速度快、全网平台可查、功能最全&#xff01; 1.想要给自己的公众号获得查题接口&#xff0c;只需要两步&#xff01; 2.题库&#xff1a; 查题校园题库&#xff1a;查题校园题库后台&…

【C++笔记】第十九篇 多态

C的多态 1. 多态简介 ① 多态是C面向对象三大特性之一。 ② 多态分为两类&#xff1a; 静态多态&#xff1a;函数重载和运算符重载属于静态多态&#xff0c;复用函数名。动态多态&#xff1a;派生类和虚函数实现运行时多态。 ③ 静态多态和动态多态区别&#xff1a; 静态…

【源码分析】Spring中的设计模式——Context与Factory的关系

省流助手 两个类都实现了同一个接口&#xff0c;但是其中一个类对接口的实现是通过调用另一个类的接口实现来实现的&#xff0c;这就是静态代理模式(也可以说是装饰器模式&#xff0c;这俩区别不大) 这个例子中就是AbstractBeanFactory和AnnotationConfigApplicationContext都…

电子签批板那个品牌好用?国产柜台电子签名板推荐

如今已正式迈入数字时代&#xff0c;电子合同、电子签名不再新奇&#xff0c;各行各业对电子签名呈现出多元化的细分需求&#xff0c;应用场景也更加广泛。目前通信、银行、保险、酒店、政务等有柜台业务服务的领域大多都已配备了电子签字板用以替代传统纸张业务办理流程。加上…

First time to know JAVA

文章目录前言1.JAVA语言概述1.1 JAVA是什么&#xff1f;1.2 JAVA语言的重要性1.3 JAVA语言的发展简史1.4 JAVA语言的特性2.初识JAVA的main方法2.1 main方法示例2.2 运行JAVA程序3.JAVA中的注释3.1 JAVA注释的基本规则3.2 JAVA注释规范4.初始JAVA中的标识符5.初始JAVA中的关键字…

pycharm中做web应用(12)基于Django和mysql 做用户登录验证2

目录pycharm中做web应用&#xff08;12&#xff09;基于Django和mysql 做用户登录验证2Django的用户验证方法Django架构的数据模型数据模型实现方法1&#xff1a;数据模型实现方法2&#xff1a;代码的实现pycharm中做web应用&#xff08;12&#xff09;基于Django和mysql 做用户…

什么蓝牙耳机听歌好?听歌音质好的蓝牙耳机推荐

蓝牙技术已经非常先进了&#xff0c;很多蓝牙耳机的音质体验可以跟有线耳机媲美了。正因为蓝牙耳机的便捷&#xff0c;越来越多的人开始选择蓝牙耳机。如果你还在纠结听歌的音质的话&#xff0c;可以看看下面几款&#xff01; 1、南卡小音舱蓝牙耳机 音质推荐指数&#xff1a…

IDERA ER/Studio Data Architect构建数据模型

IDERA ER/Studio Data Architect能够从用户的单个界面为多个数据库平台创建和管理数据模型。信息建模人员和架构师都希望对与小型业务需求相关的不同高度的数据做出反应。有一些关键行动可能希望他们的重点包括在内。 这些措施包括&#xff1a; 构建数据模型作为增长周期的一部…

LeetCode刷题day25||216.组合总和III17.电话号码的字母组合--回溯

文章目录216.组合总和III题目描述思路分析代码17.电话号码的字母组合题目描述思路分析代码216.组合总和III 题目描述 题目链接 思路分析 相对于77. 组合 (opens new window)&#xff0c;无非就是多了一个限制&#xff0c;本题是要找到和为n的k个数的组合&#xff0c;而整个集…

基于全志T133-s3(Tina Linux)移植7寸RGB显示屏驱动

基于全志T133-s3&#xff08;Tina Linux&#xff09;移植7寸RGB显示屏驱动1.硬件电路2.LCD实物图3.LCD 的驱动4.uboot配置4.1.配置文件4.2.uboot设备树5.kernel配置5.1.内核配置5.2.设备树配置6.测试屏幕7.LVGL实测1.硬件电路 2.LCD实物图 3.LCD 的驱动 Tina Linux 提供了一套…