Java小白入门必备!搞懂Java序列化?安排!

Weblogic反序列化漏洞实战:CVE-2024-2628与CVE-2024-21839深度解析 Java反序列化漏洞是应用安全领域的经典议题,其核心原理在于攻击者通过构造恶意序列化数据,在目标系统反序列化过程中触发预设的危险操作链,最终实现远程代码执行。这项技术之所以具有持久威胁性,是因为它直接利用了Java运行时环境的基础特性,能够绕过许多基于签名的传统防御机制。从技术价值看,理解反序列化漏洞的利用链构造,不仅有助于漏洞检测与防御,更是提升安全工程师底层代码审计能力的关键。在企业级Java中间件如Weblogic的攻防实战中,反序列化漏洞常通过T3、IIOP协议或特定HTTP端点触发,涉及CVE-2 阅读详情

在这里插入图片描述

什么是序列化?


一句话概括。序列化将对象的状态信息转换为可以存储或传输的形式的过程。而Java序列化,就是指把Java对象转换为“有序”字节序列的过程。相反的,把“有序”字节序列恢复为Java对象的过程称之为反序列化。

怎么理解上面的描述呢?从序列化的定义的可以看出,序列化其实是一个用来保障存储和传输的机制,而其针对的对象,肯定就是那些不便存储和传输的信息,而这体现在java编程中,就是类的实例 —— 类对象。

上面提到的“有序”,它并不是真的有顺序,其实是比较抽象化的表达,以此来表达经过序列化处理的对象,能够通过反序列化恢复成原来的样子这样一个过程

举个例子,你要搬家了,家里有个大鞋架,因为鞋架太大了,不便存储和运输,于是你把鞋机拆散了,然后把拆解步骤记录下来,运输到新家后,你再根据步骤记录把零件组装成鞋架原来的样子。拆鞋架和组装鞋架其实就是序列化和反序列的过程,而你记录的那份拆解步骤,就是序列化协议。

怎么实现序列化?


一、实现Serializable接口

定义一个类实现Serializable接口:

public class Rectangle implements Serializable {

    private int width;
    private int length;

    public Rectangle(){}

    public Rectangle(int width,int length){
        this.width = width;
        this.length = length;
    }

    public int getWidth() {
        return width;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public int getLength() {
        return length;
    }

    public void setLength(int length) {
        this.length = length;
    }

    @Override
    public String toString() {
        return "Rectangle{" +
                "width=" + width +
                ", length=" + length +
                '}';
    }

}

二、实现Externalizable接口

实现writeExternal、readExternal方法

public class Rectangle implements Externalizable {

    private int width;
    private int length;

    public Rectangle(){}

    public Rectangle(int width,int length){
        this.width = width;
        this.length = length;
    }

    public int getWidth() {
        return width;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public int getLength() {
        return length;
    }

    public void setLength(int length) {
        this.length = length;
    }

    @Override
    public String toString() {
        return "Rectangle{" +
                "width=" + width +
                ", length=" + length +
                '}';
    }

    @Override
    public void writeExternal(ObjectOutput out) throws IOException {

    }

    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {

    }
}

序列化和反序列化

public static void main(String[] args){

    /* 序列化 */
    Rectangle rectangle = new Rectangle(6,8);
    try(ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("rectangle.out"))){
        oos.writeObject(rectangle);
    }catch(Exception ex){
        ex.printStackTrace();
    }

    /* 反序列化 */
    try(ObjectInputStream ois = new ObjectInputStream(new FileInputStream("rectangle.out"))){
        Rectangle rectangle1 = (Rectangle) ois.readObject();
        System.out.println(rectangle1);
    }catch(Exception ex){
        ex.printStackTrace();
    }

}

正常的输出结果:

Rectangle{width=6, length=8}

当实现Externalizable接口,没有对writeExternal和readExternal重写时,结果如下

Rectangle{width=0, length=0}

也就是说的,实现Externalizable接口,需要自己实现序列化和反序列逻辑,编程人员用比较高的灵活度,这点在接下来的自定义序列化会讲到

自定义序列化?


transient关键字

由transient关键字修饰的成员的变量,序列化时将被忽略。该方法决定变量是否序列化。

该自定义方法级别最低,当使用的下面的任一方法时,transient关键字将失效。换句话说,使用下面各方法进行序列化自定义,那么transient修饰的变量同样会被序列化。

自定义readObject和writeObject方法

通过的类中自定义readObject和writeObject方法,可以***控制该类的序列化和反序列化逻辑***,jvm在进行序列化的时候会自动调用readObject方法,反序列化调用writeObject。

private void readObject(ObjectInputStream ois) throws IOException { 
    this.length = ois.readInt() / 100;
    this.width = ois.readInt();
}

private void writeObject(ObjectOutputStream oos)throws IOException{
    this.length = this.length * 100;
    oos.writeInt(this.length);
    oos.writeInt(this.width);
}

自定义writeReplace方法

writeReplace方法没有入参,用于***改变序列化对象的类型***,且会使用默认的序列化机。也就是说,上面提到的自定义readObject和writeObject方法都将失效。以下为实例:

private Object writeReplace() throws ObjectStreamException {

    List<Object> list = new ArrayList<>();
    list.add(this.length * 1000);
    list.add(this.width *1000);
    return list; 
}

相应的,在进行反序列化的时候,就应该使用新的类型进行接收,如该例子,应该用List<Object>接收反序列化对象。

自定义readResolve方法

readResolve方法用于***替换反序列化出来的对象***,该方法同样没有入参。

private Object readResolve() throws ObjectStreamException {

    System.out.println("自定义readResolve方法被调用");
    return new Rectangle(9,10);
}

由于没发拿到序列化的信息,因此常用来控制单例模式下,反序列化出来的对象为原先的单例对象,以维护单例模式中反序列化对象的单一性。

实现Externalizable接口

这个已经在上面实例化方式中有所提及。实现该接口必须强制实现writeExternal和readExternal 两个方法如下:

@Override
public void writeExternal(ObjectOutput out) throws IOException {
    this.length = this.length * 100;
    out.writeInt(this.length);
    out.writeInt(this.width);
}

@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
    this.length = in.readInt() / 100;
    this.width = in.readInt();
}

该效果等同于上面实现Serializable接口,然后自定义readObject和writeObjectf方法

序列化的注意事项


  1. serialVersionUID 序列化版本号

    用来区分需要序列化类的版本。假如序列化的类中发生了变量的修改,那么该版本号一般也要跟着修改,才能够在反序列化的时候得到对应版本的类对象,否则会抛出InvalidClassException异常

  2. 序列化与类的初始化一样,是的一个递归的过程。

    当一个类实现了序列化接口,该类的成员除了基本类型和String类型之外,其他的引用类型也必须是可序列化的;否则会抛NotSerializableException异常

  3. 同一对象多次序列化只会序列化一次

    如果程序对同一个对象有多次序列化,那么只会在第一次进行序列化,后续实际上是返回一个编号进行区分

  4. 反序列化的顺序与序列化时的顺序一致,类似队列模型

序列化的使用场景


讲了这么多,那序列化到底用在什么地方呢?

由jvm的内存结构相关知识我们可以知道,java对象都被保存在堆内存中。在jvm处于运行状态的时候,我们能够对对象的进行复用。但一旦jvm生命周期结束,相关对象也随之被回收。也就是说的,如果希望在jvm停止后还能够拿到某些对象,这时候就需要用到java的序列化。

因此大概由以下几种场景会使用到java的序列化

  • 当你想把的内存中的对象状态保存到一个文件中或者数据库中时候;
  • 当你想用套接字在网络上传送对象的时候;
  • 当你想通过RMI(远程方法调用)传输对象的时候;

分类: [Java基础]
标签: [java]
在这里插入图片描述

一条龙开发指南:MCP AI Agent 理论+项目实战开发你的MCP Server MCP(Model Connection Protocol)是Anthropic于2024年推出的AI模型连接协议,旨在为AI模型提供开放、通用的标准化接口,类似于“USB-C”接口,使AI模型能够无缝连接各种数据源和工具。MCP通过标准化协议解决了AI系统集成中的碎片化问题,提升了开发效率和系统可靠性。开发者可以通过简单的配置,快速接入不同的MCP Server,实现AI模型的多样化应用。MCP支持多种协议,如Stdio、SSE等,并通过JSON-RPC格式进行数据传输。文章还以腾讯云代码助手为例,展示了 阅读详情

相关推荐

利用PV操作控制进程的并发进行---经典题解

前趋图 先理清楚前趋图中的逻辑关系:P1没有前驱,P2的前驱是P1,P3的前驱是P1、P2,P4的前驱是P2,P5的前驱是P3、P4。 前驱就是指只有在前驱进程完成后,该进程才能开始执行。由图可知,这里进程之间有6条有向弧,分别表示为P1→P2,P1→P3,P2→P3,P2→P4,P3→P5,P4→P5, 各个进程间的逻辑关系,那么我们需要设定6个信号量(S1、S2、S3、S4、S5、S6),利用PV操作来控制这些过程。 对于第一个空,P1执行完成之后,需要通知P2、P3可以开始,此处需要V(S

Yan Ka Kue的博客 6138

Android程序员必备的六大顶级开发工具,快加入你的清单!

不仅仅是展示你的设备以吸引客户,还要确保你的Android应用程序在高效的时间内以最高质量构建。那么哪些是最好的Android开发者工具?有很多选择,但并非所有工具都足够好。在不浪费任何时间的情况下,让我们来看看以下的Android应用开发工具。 ###B4A你可能还没有听说过B4A(Android版Basic),这是一款简化编程的Android应用开发工具。它是一个IDE,可帮助开发人员使用BASIC编程语言创建应用程序。BASIC是一种过程编程语言,编程非常简单,因为它使用几乎普通的英语来编写代码。B4

2401_84003733的博客 2740

Adobe Acrobat Pro(Adobe PDF) - 使用技巧

Adobe Acrobat Pro为Adobe出品的PDF查看和编辑软件,下文简称Adobe PDF,该软件功能强大,拥有查看PDF、编辑PDF、打印PDF、导出PDF、合并文件、组织页面、文本标注、注释、动作向导、等功能。本文介绍Adobe PDF的一些使用技巧,最后介绍软件设置。

NSJim的博客 4万+

最全2024年终总结暨2024年计划安排,分享我在Java开发中走的一些弯路

有风险就要赶紧报出来,这样领导才会再安排人马一起把这个事情做好,你不及时报,说那么多没用的借口,出了风险你说谁担,还不是领导担,一次可能还接受,人非圣贤孰能无过嘛,但你没有养成这种习惯、没有这种闭环、上传下达的思维去做事的话,出了两三次,我相信你领导后面都不敢交核心的任务给你做了。当然你可能会说,领导安排的一些简单的活,那你就把简单的事情做到极致。对自己今年的表现还是比较满意的,刚开始接触的时候,感觉无从下手好难,但你一点一点去啃,一步一步的去邹,当你回过头来一看,喔,原来也就是那么回事。

2401_84689238的博客 1256

01-系统技术架构师必备——软件架构设计基础与核心概念

摘要 本文系统阐述了软件架构设计的核心概念与方法论,重点涵盖以下内容:1)软件架构的四大要素(构件、连接件、约束、配置)及其边界划分;2)Garlan & Shaw五大架构风格(数据流、调用/返回、独立构件、虚拟机、仓库)的典型应用场景;3)基于电商库存系统的架构选型实战案例,展示如何根据业务需求(高并发、最终一致性)选择事件驱动架构配合Saga模式;4)介绍ABSD、DSSA等主流架构方法论及ISO/IEEE标准体系。文章融合金融与互联网领域的架构实践经验,为技术架构师提供系统性的知识框架和决策参考。

模界 | AI工程化实践者 183

增益调度控制 —— 理论、案例与交互式 GUI 实现

本文详细介绍了增益调度控制的基本原理、数学模型及公式推导,探讨了该方法在适应非线性系统和大范围工作条件下的优势与局限。通过航空飞行控制、发动机推力控制以及化工过程控制三个典型案例,我们展示了如何利用调度变量动态调整控制增益,从而使得控制系统在各个工作点均能达到优良性能。为帮助工程师和研究者更直观地理解并验证增益调度控制的实际效果,本文提供了一套基于 Python 与 PyQt6 的交互式 GUI 控制系统代码。用户不仅可以实时查看仿真数据,还能通过在线调节参数直观体验调度控制的优势。

闲人编程的博客 1481

华为4面技术5面HR,给大家安排上!

前言 一次偶然,从朋友那里得到一份“java高分面试指南”,里面涵盖了25个分类的面试题以及详细的解析:JavaOOP、Java集合/泛型、Java中的IO与NIO、Java反射、Java序列化、Java注解、多线程&并发、JVM、Mysql、Redis、Memcached、MongoDB、Spring、Spring Boot、Spring Cloud、RabbitMQ、Dubbo 、MyBatis 、ZooKeeper 、数据结构、算法、Elasticsearch 、Kafka 、微服务、Linu

m0_56824583的博客 258

04-协议基础03:USB 2.0信号与电气特性

USB 2.0使用两根差分信号线D+/D-进行数据传输,支持低速(1.5Mbps)、全速(12Mbps)和高速(480Mbps)三种速率。USB总线为主从模式,所有事务由Host发起。端电阻值作用HostRpd(D+)15KΩ±5%下拉,默认低电平HostRpd(D-)15KΩ±5%下拉,默认低电平全速设备Rpu(D+)1.5KΩ±5%上拉到3.3V,标识全速低速设备Rpu(D-)1.5KΩ±5%上拉到3.3V,标识低速USB 2.0硬件要点。

内核笔记 105

2019年终总结暨2020年计划安排

一、前言 转眼间,2019年即将成为过去式了。不知道小伙伴们在生活中或者工作中过得开心不。2019年IT行业发生了很多大事,比如“996”,想必大家都知道,一度登顶Github热榜,Python之父也参与其中,影响力可想而知。前段时间又是网易裁员、华为裁员,一波接一波的裁员潮。不知道你们是否有一些思考,我自己有以下几点思考: 1、要有老板思维 不要做资本家的代码输出机器,自己要慢慢蓄势、一点点积累...

riemann_的博客 1448

2026年1至9月武汉市房地产价格深度分析报告

本报告基于2026年1月至9月武汉市实际成交案例,从成交价格、区域分布、户型结构、价格走势等维度进行深度分析。数据来源包括武汉市住房保障和房屋管理局备案数据、主要中介机构成交记录及典型楼盘网签案例,覆盖全市15个行政区及主要功能板块。

王国平的博客 336

图像分割 - 使用Mask R-CNN模型在COCO数据集上进行图像分割任务

图像分割是计算机视觉领域的一个重要任务,它旨在将图像中的每个像素分类为对象或背景。Mask R-CNN是一种基于区域的卷积神经网络,可用于图像分割任务。它是Faster R-CNN的扩展,将目标检测与图像分割结合起来,能够同时检测和分割对象。在本博客中,我们将使用Mask R-CNN模型在COCO数据集上进行图像分割任务。我们将介绍如何下载和准备COCO数据集,以及如何使用Mask R-CNN模型进行训练和推理。

斌擎科技 1190

【面试必备】Android快速转战Kotlin教程,offer拿到手软

前情 首先介绍一下自己的情况吧,由于当年高中年少轻狂,不努力,差二本线16分。我自己也没有意识到学历的区别,最终听了家里的安排上了一个专科,电气专业。 现在想想都很后悔,当年为什么没有自己的主见,如果复读或者读三本都比这个好很多。后来也算是意识到了自己学历的不足吧,先是专升本,然后就是考研。 也是自己的基础不行吧,最后调剂到一所双非的大学读计算机专业,基础不好,什么都是自学。 在学校,找了一个导师,接触到Android,刚开始什么都不会,看着视频学java,Android开发,慢慢入了门,但是也只处于入门阶

m0_53537576的博客 133

基于自适应小波阈值算法的图像去噪

自适应小波阈值算法是一种基于小波变换的方法,它相对于传统的小波阈值去噪方法具有更好的性能和鲁棒性。该算法首先对图像进行小波变换,然后根据小波系数的大小确定一个自适应的阈值,将小波系数与阈值进行比较,大于阈值的系数被保留,小于阈值的系数被置零。在上述代码中,首先选取了小波函数sym4进行小波分解,然后根据标准差计算出阈值,使用wthresh函数进行阈值处理,最后进行反变换得到处理后的图像。该GUI界面与前面的自适应小波阈值算法代码结合,实现了图像的去噪,并提供了可视化的效果。

与其临渊羡鱼,不如退而结网 559

秋招成功上岸互联网大厂必备之Java面试题:初级-中级-高级!

现在已经是25年8月份了,准备秋招面试的Java程序员,可以通过明确面试考察点、分类刷题、模拟面试、记录错题、总结归纳等方法来高效地刷面试题。22.String str="a"与 String str=new String("a")一样吗?6.SpringCloud和Dubbo区别?25.Java虚拟机退出时Daemon线程中的finally块一定会执行?18.Java中final、finally、finalize的区别与用法。9.Mybatis中9个动态标签是?10.xml映射文件中,有哪些标签?

马士兵教育 881

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

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

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

Java面试必问!入职3个月的Java程序员面临转正

一、网络原理 OSI 与 TCP/IP 各层的结构与功能,都有哪些协议 TCP 建立连接的过程,为什么要三次握手? TCP、UDP 协议的区别,各自的应用场景 打开浏览器,输入 URL 地址,访问主页的过程 HTTP 有哪些方法? HTTP 和 HTTPS 有什么区别? 二、Java 核心技术 HashMap 底层数据结构是什么,时间复杂度多少? JDK 8 中对 HashMap 做了怎样的优化? HashMap 和 TreeMap 什么区别? ConcurrentHashMap 的实现原理 包装类的

m0_56830725的博客 463

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

别踩坑!想自学网络安全(黑客技术),首先你得了解 什么是网络安全!什么是黑客!

想自学网络安全(黑客技术),首先你得了解 什么是网络安全!什么是黑客!

2301_77472496的博客 852

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

10个艰难的Java面试题与答案(2)

看完美团、字节、腾讯这三家的面试问题,是不是感觉问的特别多,可能咱们又得开启面试造火箭、工作拧螺丝的模式去准备下一次的面试了。开篇有提及我可是足足背下了1000道题目,多少还是有点用的呢,我看了下,上面这些问题大部分都能从我背的题里找到的,所以今天给大家分享一下互联网工程师必备的面试1000题。注意不论是我说的互联网面试1000题,还是后面提及的算法与数据结构、设计模式以及更多的Java学习笔记等,皆可分享给各位朋友互联网工程师必备的面试1000题而且从上面三家来看,算法与数据结构是必备不可少的。

2301_76348344的博客 398

从小白到大神?零基础黑客(白帽)技术入门秘籍,看这一篇就够了!开启你的开挂人生

但无论哪个过程,都需要花费很长的时间与精力去学习与钻研。上面这部分是学习网络安全必备的基础,这部分内容没有多大难度,也没有任何的逻辑性难度,只要多练多看,这部分内容就是熟能生巧的事情。

2301_79455190的博客 64

我在阿里的一次JAVA面试经历总结(跳槽,深薪必备)

为记录阿里的电面经历,特与大家分享,岗位是JAVA研发工程师。 一面主要问题如下: 1)首先自我介绍 2)数据结构算法的基本问题,如排序算法,二叉树遍历,后序遍历非递归,图的最短路径问题 3)对一个数组进行绝对值排序的算法 4)java中hashmap的底层实现 5)java中垃圾回收机制GC原理等 6)介绍自己的项目,数据库中用到的数据结构数据模型,死锁的概念(问的应该是数据库的死...

weixin_45127309的博客 422

零基础黑客网络安全入门指南:保姆级学习路线与必备技能,收藏这一篇就够了!

网络安全产业就像一个江湖,各色人等聚集。相对于欧美国家基础扎实(懂加密、会防护、能挖洞、擅工程)的众多名门正派,我国的人才更多的属于旁门左道(很多白帽子可能会不服气),因此在未来的人才培养和建设上,需要调整结构,鼓励更多的人去做“正向”的、结合“业务”与“数据”、“自动化”的“体系、建设”,才能解人才之渴,真正的为社会全面互联网化提供安全保障。

2401_84206094的博客 843

学习指南!Android架构师必备框架技能核心笔记,高级面试题+解析

前言 下面的题目都是大家在面试字节跳动或者其它大厂面试时经常遇到的,如果大家有好的题目或者好的见解欢迎分享。 参考解析:郭霖、鸿洋 内容特点:条理清晰,含图像化表示更加易懂。 内容概要:包括 Handler、Activity相关、Fragment、service、布局优化、AsyncTask相关、Android 事件分发机制、 Binder、Android 高级必备 :AMS,WMS,PMS、Glide、 Android 组件化与插件化等面试题和技术栈! 接下来我们针对字节跳动Android中高级面试展开的

m0_57066201的博客 223

2019配置gradle详解_收藏必备 | 享学课堂2019年精选内容汇总

是好东西就一定要点击文末“在看”记得分享给好友哦!大咖讲座视频:高清无码!《亿级流量》作者张开涛老师的视频资源要不要???视频:腾讯高级工程师现场精解分布式系统中的数据一致性视频:高级架构师讲述58快狗打车订单调度系统从0到1的架构演变视频:谈笑间,程序员的人生被安排一遍又一遍视频:阿里资深架构师详解高并发秒杀系统,面试再也不担心答不上!视频:阿里资深架构师详解高并发秒杀系统,面试再也不...

weixin_28862545的博客 432

2023年金九银十最新【Java八股文1000道】基础、中高级面试必备,查漏补缺

希望看到这篇文章的小伙伴都能抓住金九银十的机会,拿到自己想要的 Offer!

qq13321123的博客 108

一篇JVM详细图解,坚持看完!带你真正搞懂Java虚拟机!

一篇JVM详细图解,坚持看完!带你真正搞懂Java虚拟机!Java虚拟机1、JVM简介2、JVM内存区域2.1、程序计数器(线程私有)2.2、虚拟机栈(线程私有)2.3、本地方法区(线程私有)2.4、堆(Heap-线程共享)2.5、方法区/永久代(线程共享)3、JVM类加载器4、双亲委派机制5、沙箱安全机制6、GC垃圾回收算法6.1、如何确定垃圾6.2、标记清除算法(Mark-Sweep)6.3、复制算法(copying)6.4、标记整理算法(Mark-Compact)6.5、分代收集算法 Java虚拟机.

Delilah_java的博客 1万+
上一篇: 华为二面被问“Linux系统配置文件”,教你一招怒怼面试官!
下一篇: 一篇JVM详细图解,坚持看完!带你真正搞懂Java虚拟机!
Danny_java
博客等级 码龄5年 9粉丝 64原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值