《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 小时前
Springboot3.5.x结构化日志新属性
spring boot·后端·spring
涡能增压发动积1 小时前
一起来学 Langgraph [第三节]
后端
sky_ph1 小时前
JAVA-GC浅析(二)G1(Garbage First)回收器
java·后端
涡能增压发动积1 小时前
一起来学 Langgraph [第二节]
后端
hello早上好2 小时前
Spring不同类型的ApplicationContext的创建方式
java·后端·架构
roman_日积跬步-终至千里2 小时前
【Go语言基础【20】】Go的包与工程
开发语言·后端·golang
00后程序员3 小时前
提升移动端网页调试效率:WebDebugX 与常见工具组合实践
后端
HyggeBest3 小时前
Mysql的数据存储结构
后端·架构
TobyMint3 小时前
golang 实现雪花算法
后端
G探险者4 小时前
【案例解析】一次 TIME_WAIT 导致 TPS 断崖式下降的排查与优化
后端