《Effective Java》-序列化

序列化

Item 85: Prefer alternatives to Java serialization

其他方法优先于Java序列化

使用Java中的readObject()方法进行反序列化是非常有风险的。

其一,为反序列化提供精心编写的代码流,则攻击者可以在底层硬件中执行本机的的任意代码。

其二,当攻击者向服务发送反序列化炸弹(deserialize bomb),就能够轻易完成一次拒绝服务(Denail of Service)攻击。

避免序列化攻击的最佳方式就是永远不要反序列化任何东西。 没有理由在你写的任何程序中使用Java序列化。

如果非要使用Java序列化,使用Java 9 支持的java.io.ObjectInputFilter

Item 86: Implement Serializable with great caution

谨慎地实现Serializable接口。

实现Serializable接口最大的代价就是,一旦某个类被发布,被存储在硬盘中,他可修改的灵活性就大大降低了。

如果使用了默认的序列化方式,一旦类的内部形式发生改变,那么发序列化老数据的时候,就会产生兼容性的问题。

实现序列化接口的第二个代价就是,会增加安全漏洞以及BUG的几率。通过序列化来创建对象,是一种超出语言之外的机制,很容易跳过系统的安全检查。

第三个代价是,增加了新类的测试负担。

如果一个专门为继承而生的类,和接口应当尽可能少地去实现序列化接口。内部类不应该去实现序列化接口

Item 87: Consider using a custom serialized form

考虑使用自定义的序列化形式。

在深思熟虑之前,不要贸然接受默认的序列化形式。

如果一个对象的物理表现形式和逻辑内容相同,可以考虑使用默认的序列化形式。不过,即使你确定了使用默认的序列化形式是合适的,依旧需要提供一个readObject方法来确保约束关系和安全性。

如果将某些字段设置为transient,那么反序列化的时候,字段值将会被初始化为默认值。如果是引用数据类型,则为null,基本数据类型则为0或者false。如果不能接受的话,必须提供readObject,在其实现内为你想要的属性去赋值。

此外,如果你在读取对象状态的其他方法上施加了同步,则也必须在序列化上强制这种同步。

一定要为实现序列化接口的类显式地声明一个序列化UID。不要去随意修改这个UID,除非你想要放弃系统的兼容性。

Item 88: Write readObject methods defensively

保护性地编写readObejct方法

当一个对象被反序列化的时候,若其某个字段包含客户端不存在的引用,则对此字段的保护性拷贝是至关重要的。

可以通过一个石蕊测试来确定,你是应该使用默认的readObject还是需要定义自己的readObject:你觉得为所有的非transient字段都添加到一个公有构造器,并且并施加任何参数校验是否合适?

禁止在readObject方法中引用任何用于被重写的方法。

Item 88: For instance control, prefer enum types to readResolve

为了控制实例,枚举类型优先于readResolve

对于任何的readObject方法,无论是显式的还是默认的,都会返回一个新的实例,该实例不同于创建时的实例。

readResolve的上述性质会破坏单例模式,为了保证单例的性质,可以使用枚举类对象。

事实上,如果你依赖于readResolve控制实例,所有的字段都应该被声明为transient的。

Item 90: Consider serialization proxies instead of seriallized instance

考虑使用序列化代理替代序列化实例

序列化模式相当简单:

  1. 为可序列化的类设计一个私有的静态嵌套类,精确表示外围类的逻辑状态
  2. 嵌套类的参数类型是外围类,并且拥有一个构造方法
  3. 构造器只从其参数中来复制值,而不做任何参数检查或者保护性拷贝

序列化代理有两个局限性:

  1. 不能与可以被客户端扩展的类相兼容
  2. 序列化代理模式增强的功能和安全性并不是没有代价的,保护性拷贝会降低系统的运行效率
相关推荐
拉丁解牛说技术4 分钟前
AI大模型进阶系列(01)AI大模型的主流技术 | AI对普通人的本质影响是什么?
后端·架构·openai
normaling9 分钟前
四,java集合框架
后端
lovebugs13 分钟前
K8s面试第一篇:初识Kubernetes——核心概念与组件详解
后端·算法·面试
阁阁下18 分钟前
springcloud configClient获取configServer信息失败导致启动configClient注入失败报错解决
后端·spring·spring cloud
JavaPub-rodert21 分钟前
一道go面试题
开发语言·后端·golang
AronTing23 分钟前
05-Spring Security 认证与授权机制源码解析
后端·面试
6<724 分钟前
【go】静态类型与动态类型
开发语言·后端·golang
lamdaxu26 分钟前
Arthas基础
后端
技术liul30 分钟前
解决Spring Boot Configuration Annotation Processor not configured
java·spring boot·后端
小华同学ai36 分钟前
1K star!这个开源项目让短信集成简单到离谱,开发效率直接翻倍!
后端·程序员·github