Java中访问修饰符在序列化反序列化时能否绕过 `private` 限制恢复对象状态

小丽小哥_2832

小丽小哥_2832

2026-09-17

188人浏览

原创

java序列化机制天然绕过private访问限制,直接序列化和恢复private字段,因jvm内置协议无视访问修饰符,仅受transient、static及自定义序列化方法影响。

java中访问修饰符在序列化反序列化时能否绕过 `private` 限制恢复对象状态

Java 中的 private 修饰符在序列化与反序列化过程中不会构成障碍——它天然被绕过,无需反射、无需 setAccessible(true),也不依赖任何额外操作。

这是因为 Java 序列化机制的设计原则:只关注字段是否存在、是否被 transient 修饰,而完全忽略访问级别private 字段默认会被序列化,反序列化时也会原样恢复。


private 字段能被序列化和反序列化的根本原因

  • Serializable 是一个标记接口,不提供方法,但触发 JVM 内置的序列化协议;
  • 序列化过程由 ObjectOutputStream 调用 writeObject() 启动,底层通过 ObjectStreamClass 反射获取所有transient、非 static 成员字段(无论 public/protected/private);
  • 反序列化时,ObjectInputStream.readObject() 使用特殊机制(ObjectStreamClass.newInstance())直接构造对象,跳过构造函数,并逐个填充字段值——这个过程绕过所有 Java 访问控制检查,包括 private

✅ 示例验证:

Alibabacloud Sdk Client Initialization For Java
Alibabacloud Sdk Client Initialization For Java

在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。

下载
public class User implements Serializable {
    private static final long serialVersionUID = 1L;
    private String name = "Alice";
    private int age = 30;
    private transient String token = "secret"; // 不会序列化
}

序列化后写入文件,再反序列化读出:nameage 的值完整恢复,tokennull(因 transient)——private 没有任何影响。


为什么 private 在这里“失效”?不是 bug,是设计

  • 封装(private)是编译期+运行期的语义约束,用于规范正常代码调用路径;
  • 序列化/反序列化属于JVM 级别的对象状态快照与重建机制,它不走普通 new + 构造器流程,而是走专用字节流协议;
  • JVM 明确允许该机制访问 private 字段,这是 Serializable 协议的一部分,不是反射破防,也不是安全漏洞。

需要注意的例外与边界情况

  • transient 字段:显式声明为 transientprivate 字段不会被序列化,反序列化后为默认值(如 null0false);
  • static 字段:无论是否 private一律不参与序列化(属于类状态,非实例状态);
  • 自定义序列化(writeObject/readObject):若重写了这两个私有方法,JVM 会调用它们,此时你可完全控制哪些字段写入/读取,private 字段仍可自由访问;
  • 模块化限制(Java 9+):如果类在未开放(opens)的模块中,且你用反射手动读写 private 字段(非序列化本身),才可能触发 IllegalAccessError;但标准序列化不受此限——它是 JVM 白名单行为。

对单例等敏感模式的实际影响

  • 单例被反序列化破坏,不是因为 private 失效了,而是因为反序列化根本不调用构造器
  • 即便构造器是 privateObjectInputStream 仍能新建一个“新实例”,导致单例唯一性崩塌;
  • 解决方案不是加 private,而是实现 readResolve()
    private Object readResolve() {
        return getInstance(); // 返回已有单例,丢弃新反序列化出的对象
    }

总结一句话

private 在 Java 序列化与反序列化中不生效、不拦截、不报错——它本就不该在这里起作用。序列化是 JVM 特权操作,private 是面向开发者编码的封装契约,二者作用域不同。真正需要你主动管控的,是 transientserialVersionUIDreadResolve 这些显式可控点。

Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南

相关专题

更多
java
java

Java是一个通用术语,用于表示Java软件及其组件,包括“Java运行时环境 (JRE)”、“Java虚拟机 (JVM)”以及“插件”。php中文网还为大家带了Java相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

2023.06.15

8617

6

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

2023.07.05

5822

9

java自学难吗
java自学难吗

Java自学并不难。Java语言相对于其他一些编程语言而言,有着较为简洁和易读的语法,本专题为大家提供java自学难吗相关的文章,大家可以免费体验。

2023.07.31

5252

8

java配置jdk环境变量
java配置jdk环境变量

Java是一种广泛使用的高级编程语言,用于开发各种类型的应用程序。为了能够在计算机上正确运行和编译Java代码,需要正确配置Java Development Kit(JDK)环境变量。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.01

964

3

java保留两位小数
java保留两位小数

Java是一种广泛应用于编程领域的高级编程语言。在Java中,保留两位小数是指在进行数值计算或输出时,限制小数部分只有两位有效数字,并将多余的位数进行四舍五入或截取。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.02

808

3

java基本数据类型
java基本数据类型

java基本数据类型有:1、byte;2、short;3、int;4、long;5、float;6、double;7、char;8、boolean。本专题为大家提供java基本数据类型的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

1136

5

java有什么用
java有什么用

java可以开发应用程序、移动应用、Web应用、企业级应用、嵌入式系统等方面。本专题为大家提供java有什么用的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

2269

5

java在线网站
java在线网站

Java在线网站是指提供Java编程学习、实践和交流平台的网络服务。近年来,随着Java语言在软件开发领域的广泛应用,越来越多的人对Java编程感兴趣,并希望能够通过在线网站来学习和提高自己的Java编程技能。php中文网给大家带来了相关的视频、教程以及文章,欢迎大家前来学习阅读和下载。

2023.08.03

19631

3

配置java环境变量
配置java环境变量

配置Java环境变量是为了让操作系统能够识别和使用Java的相关命令和功能。本专题为大家提供配置java环境变量相关文章,帮助大家解决问题。

2023.08.03

1035

8

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
dev.java 官方:Learn Java
dev.java 官方:Learn Java

共0课时 | 0人学习

Java JDBC数据库连接官方教程
Java JDBC数据库连接官方教程

共0课时 | 0人学习