《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. 序列化代理模式增强的功能和安全性并不是没有代价的,保护性拷贝会降低系统的运行效率
相关推荐
间彧1 小时前
Kubernetes的Pod与Docker Compose中的服务在概念上有何异同?
后端
间彧1 小时前
从开发到生产,如何将Docker Compose项目平滑迁移到Kubernetes?
后端
间彧1 小时前
如何结合CI/CD流水线自动选择正确的Docker Compose配置?
后端
间彧1 小时前
在多环境(开发、测试、生产)下,如何管理不同的Docker Compose配置?
后端
间彧1 小时前
如何为Docker Compose中的服务配置健康检查,确保服务真正可用?
后端
间彧1 小时前
Docker Compose和Kubernetes在编排服务时有哪些核心区别?
后端
间彧1 小时前
如何在实际项目中集成Arthas Tunnel Server实现Kubernetes集群的远程诊断?
后端
brzhang2 小时前
读懂 MiniMax Agent 的设计逻辑,然后我复刻了一个MiniMax Agent
前端·后端·架构
草明3 小时前
Go 的 IO 多路复用
开发语言·后端·golang
蓝-萧3 小时前
Plugin ‘mysql_native_password‘ is not loaded`
java·后端