使用枚举实现单例模式,不会反序列化破坏攻击,不会被反射破坏攻击。(附带枚举单例的简单实现)

原因分析

1.反序列化方法

 jdk8中的Enum源码中对反序列化方法进行重写,抛出异常。

  • java.lang.Enum#readObject方法截图如下

②java.io.ObjectInputStream#readObject 方法中的 readEnum 方法处理了枚举类型的反序列化,从而确保了枚举的单例特性。

具体来说,在 Java 的序列化过程中,当对象被反序列化时,ObjectInputStream 类会调用 readObject 方法来读取对象。对于枚举类型,readObject 方法会调用 readEnum,后者会根据枚举的类型和名称来查找已经存在的枚举常量:Enum.valueOf()。

  • java.io.ObjectInputStream#readObject方法截图如下

  • java.io.ObjectInputStream#readEnum方法截图如下,包含Enum.valueOf()

这一过程确保了以下几点:

  1. 确保单例性readEnum 方法通过调用 Enum.valueOf() 来查找与名称匹配的枚举常量,这意味着无论你如何尝试反序列化,得到的都是已经存在的枚举实例,保证了枚举的单例特性。

  2. 防止实例创建:由于枚举的构造函数是私有的,而且在反序列化过程中不会直接调用构造函数,因此无法创建新的枚举实例。

2.反射newInstance()方法

在 Java 中,使用反射的 java.lang.reflect.Constructor#newInstance 方法来创建枚举类的实例时,会进行特殊的检查。

如果尝试通过反射调用 newInstance 方法来创建一个枚举类型的实例,Java 会抛出 IllegalArgumentException,并指出 "Cannot reflectively create enum objects"。这一设计是为了保护枚举类型,确保它们的实例唯一性。

如下代码:

枚举在 Java 中被设计为单例,每一个枚举常量在一个应用程序的生命周期中只能存在一个实例。由于枚举常量在定义时就已经实例化,Java 不允许通过反射来创造额外的枚举实例。这一机制通过阻止反射创建枚举对象,进一步增强了枚举的安全性和一致性。

因此,结合 ObjectInputStream 在反序列化时对枚举类型的特殊处理和反射机制的限制,共同保证了枚举类型不会被意外或者恶意地创建多个实例。


Enum的反编译

Enum 类型的静态初始化(static

枚举类在类加载时,会静态初始化并创建实例,这一过程是由 JVM 保证的。因此,枚举类型的实例是在类加载时就已经创建好了,而反序列化时只是获取这个已存在的实例。这种机制避免了创建多个枚举实例的风险。

枚举的反编译,属性都有static修饰。


单例模式示例

假设有一个简单的枚举单例类:

import java.io.Serializable;

public enum Singleton implements Serializable {
    INSTANCE;

    public void someMethod() {
        System.out.println("This is a method in the Singleton instance.");
    }
}

反射攻击与反序列化攻击

通常,在实现单例模式时,使用反射可以绕过单例的构造方法,从而创建多个实例。而反序列化攻击则是通过反序列化创建新实例,绕过单例的构造过程。

有人说枚举单例不会被破坏是因为:

普通类的反序列化使用了unsafe,枚举没有使用。

在 Java 中,反序列化的过程是为了将序列化的字节流转换回对象。为了提高性能,Java 的反序列化机制使用了 Unsafe 类来直接操作内存。普通类的反序列化可能会涉及到创建新的对象实例,这时使用 Unsafe 可以避免调用构造函数,从而提高效率。

然而,对于枚举类来说,Java 语言设计上已经保证了枚举实例是唯一的(即单例)的。在反序列化过程中,枚举的实例是通过 Enum.valueOf() 方法进行查找的,这个方法会在枚举值唯一的情况下返回已存在的实例,而不是创建新的实例。

如有说错的地方请大家及时指出以免误导他人


参考

你知道吗?枚举单例模式是世界上最好的单例模式!-CSDN博客

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

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

相关文章

数据挖掘之聚类分析

聚类分析(Clustering Analysis) 是数据挖掘中的一项重要技术,旨在根据对象间的相似性或差异性,将对象分为若干组(簇)。同一簇内的对象相似性较高,而不同簇间的对象差异性较大。聚类分析广泛应用…

【C++】判断能否被 3, 5, 7 整除问题解析与优化

博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 💯前言💯题目描述💯老师代码实现与分析老师代码逻辑分析优点缺点 💯学生代码实现与分析学生代码逻辑分析优点缺点 💯改进与优化优化代码实现优化…

PHP开发日志 ━━ 基础知识:四种不同的变量返回方式该如何调用

最近在给框架升级,其中涉及到古早的缓存系统升级,现在准备区分类型为混合、变量和普通文件,那么变量用什么形式存储到缓存才能给后续开发带来便利和通用性呢?于是就涉及到了本文的php基础知识。 好吧,又是一个无用的知…

Y3编辑器教程5:触发器进阶使用(镜头、UI、表格、函数库、排行榜、游戏不同步)

文章目录 一、游戏声音设计二、 游戏镜头设计2.1 镜头的基本参数2.2 镜头时间轴动画 三、界面编辑3.1 界面编辑器设置3.2 添加按钮事件3.3 触发编写 四、 表格编辑器(实现对话UI)4.1 一维表和多维表4.2 数据验证、搜索、保存与撤销4.3 Excel导入导出4.4 …

高中数学:成对数据的统计分析

文章目录 一、成对数据的统计相关性1、相关关系2、样本相关系数 二、一元线性回归模型及其应用1、一元线性回归模型2、最小二乘估计3、拟合效果比较公式4、注意点5、例题 三、列联表与独立性检验1、分类变量2、分类变量与列联表3、独立性检验4、常用小概率值和临界值5、例题6、…

Python OCR文字识别api接口

一.引言 文字识别,也称为光学字符识别(Optical Character Recognition, OCR),是一种将不同形式的文档(如扫描的纸质文档、PDF文件或数字相机拍摄的图片)中的文字转换成可编辑和可搜索的数据的技术。随着技…

Type-C接口电热毯的创新之旅

在科技日新月异的今天,智能家居产品正逐步渗透到我们生活的每一个角落,从智能灯光到温控系统,无一不展现着科技带来的便捷与舒适。而在这个追求高效与智能化的浪潮中,一款结合了最新科技元素的电热毯——Type-C接口电热毯&#xf…

【Unity3D】实现UGUI高亮引导点击

Unity版本2019.4.0f1 Personal <DX11> using UnityEngine; using UnityEngine.UI;public class GuideMask : MonoBehaviour, ICanvasRaycastFilter {public Canvas canvas;public Transform guideTargetTrans;public Image image;private Vector3 guideTargetWorldPos;pr…

docker启动一个helloworld(公司内网服务器)

这里写目录标题 容易遇到的问题&#xff1a;1、docker连接问题 我来介绍几种启动 Docker Hello World 的方法&#xff1a; 最简单的方式&#xff1a; docker run hello-world这会自动下载并运行官方的 hello-world 镜像。 使用 Nginx 作为 Hello World&#xff1a; docker…

Redisson常用方法

Redisson 参考: 原文链接 定义&#xff1a;Redisson 是一个用于与 Redis 进行交互的 Java 客户端库 优点&#xff1a;很多 1. 入门 1.1 安装 <!--redission--> <dependency><groupId>org.redisson</groupId><artifactId>redisson</artifa…

火焰传感器与C++编程:精准检测火灾的技术实现

火灾是我们日常生活中一个不可忽视的安全隐患&#xff0c;而火灾报警系统的实现可以大大提高我们的安全保障。通过嵌入式技术和传感器&#xff0c;我们能够在第一时间识别火灾隐患并发出警报。火焰传感器作为一种专门用于火灾监测的传感器&#xff0c;能高效地通过红外线&#…

arcGIS使用笔记(无人机tif合并、导出、去除黑边、重采样)

无人机航拍建图之后&#xff0c;通过大疆智图软件可以对所飞行的区域的进行拼图&#xff0c;但是如果需要对拼好的图再次合并&#xff0c;则需要利用到arcGIS软件。下面介绍arcGIS软件在这个过程中常用的操作。 1.导入tif文件并显示的方法&#xff1a;点击“”图标进行导入操作…

VMware Workstation的有线连接消失了

进入/var/lib目录下 cd /var/lib 查看是否存在NetworkManager 文件 ls 将其删除&#xff0c;然后虚拟机reboot一下。 sudo rm -r NetworkManager reboot 解决了&#xff0c;可以联网

算法-动态数组-62.不同路径

一、题目 二、思路解析 1.思路&#xff1a; 对于找到目的地它的来源主要来源于目的地的上一格和目的地的左一格 2.常用方法&#xff1a; 无 3.核心逻辑&#xff1a; 1.处理边界&#xff1a; a.只向右移动&#xff0c;至始至终只有一条路径 for(int i0;i<m;i){dp[i][0]1; } …

C# 探险之旅:第三十节 - 类型class(继承Inheritance) —— 当“儿子”继承“老爸”的遗产

嘿&#xff0c;探险家们&#xff01;欢迎再次踏上我们的C#奇幻旅程。今天&#xff0c;我们要聊一个既有趣又实用的话题——继承&#xff08;Inheritance&#xff09;&#xff01;想象一下&#xff0c;如果你的“儿子”能够继承“老爸”的遗产&#xff0c;那编程世界里的对象们也…

Qt:Q_GLOBAL_STATIC实现单例(附带单例使用和内存管理)

转载 https://blog.csdn.net/m0_71489826/article/details/142288179 前言 本文主要写Q_GLOBAL_STATIC实现单例以及单例的释放&#xff0c;网上很多教程只有单例的创建&#xff0c;但是并没有告诉我们单例的内存管理&#xff0c;这就很头疼。 正文 使用 Qt 的 Q_GLOBAL_STA…

12.5【Java exp4】【DEBUG】

pro1 JwtAuthenticationFilter 类在两个不同的位置被定义了&#xff0c;导致Spring无法确定使用哪个定义。 为了解决这个问题&#xff0c;你可以采取以下几种方法之一&#xff1a; 检查类路径中的重复类&#xff1a; 确保 JwtAuthenticationFilter 类没有在多个地方被定义。检…

C++11语法解析(二)

可变参数模板 基本语法及原理 ・C11 支持可变参数模板&#xff0c;也就是说支持可变数量参数的函数模板和类模板&#xff0c;可变数目的参数被称为参数包&#xff0c;存在两种参数包&#xff1a;模板参数包&#xff0c;表示零或多个模板参数&#xff1b;函数参数包&#xff1…

《知识拓展 · 统一建模语言UML》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…

轻量级日志管理平台:Grafana Loki搭建及应用(详细篇)

前言 Grafana Loki是Grafana Lab团队提供的一个水平可扩展、高可用性、多租户的日志聚合系统&#xff0c;与其他日志系统不同的是&#xff0c;Loki最初设计的理念是为了为日志建立标签索引&#xff0c;而非将原日志内容进行索引。 现在目前成熟的方案基本上都是&#xff1a;L…