任何服务器、框架或 J2EE 本身是否仍在 Java 中的任何地方使用序列化?

Is Serialization still used anywhere in Java by any servers, frameworks or J2EE itself?

有这个 Sonar rule 称为 “可序列化”class 中的字段应该是瞬态的或可序列化的。当您向 class 添加一个不可序列化的字段时,它会出现。规则规定:

For instance, under load, most J2EE application frameworks flush objects to disk, and an allegedly Serializable object with non-transient, non-serializable data members could cause program crashes, and open the door to attackers.

这对我来说听起来已经过时了。在 Effective Java 第 3 版 中指出,在开发新软件时,序列化是不相关的。另外,Removing Serialization from Java Is a 'Long-Term Goal' at Oracle。 Java 首席架构师本人 Mark Reinhold 表示

„Serialization was a horrible mistake in 1997.“

这个问题,如果 Spring 框架可以刷新对象,已经在这里问过:

所以我问这个问题: 是否有任何现代应用程序服务器、框架或 J2EE 实现本身(尤其是 Java 与 CDI、EJB、JPA 交互的组件)在重负载下将对象刷新到磁盘?

或者这个说法已经过时了?

TL;DR

如果您没有实现可分发的 Web 应用程序,您没有启用会话持久性,并且您只使用内存缓存,那么您可能不需要在任何地方使用 Serializable。

说明

对于会话复制,Java序列化对于最新的 Servlet 规范来说仍然是必须的:https://jakarta.ee/specifications/servlet/5.0/jakarta-servlet-spec-5.0.html#distributed-environments

一个常见的用例是,如果您在负载均衡器后面有多个服务器,并且您在一个服务器上登录,您将获得一个 JSESSIONID cookie。如果负载均衡器将您发送到不同的服务器以进行下一个请求,您的登录属性和其他会话范围的属性将被序列化并复制到新服务器上,因此您的 JSESSIONID 在那里仍然有效。

您需要为会话范围的属性序列化的另一个用例是当应用程序服务器决定将会话交换到磁盘时。例如Tomcat 8、这个可以配置为当会话太多无法保存在内存中时激活,或者当服务器重启时,你想保持会话存活。看 https://tomcat.apache.org/tomcat-9.0-doc/config/manager.html

对于这些类型的用例,每个 Servlet-5.0 兼容的应用程序服务器都必须默认支持 Http 会话中的可序列化对象。

对于某些服务器,可以通过使用例如Jackson-JSON 序列化或类似的东西。参见例如

另一个常见的用例是缓存。这用于使对象尽可能快地访问,最好是在内存中,但可能会暂时卸载到磁盘或外部缓存服务器。 它有一个标准 API (JSR-107),明确选择不需要序列化对象,但大多数实现仍然默认使用 java 卸载部分的序列化。

您可以再次调整它们以支持其他序列化机制,例如对于 ehcache:https://www.ehcache.org/documentation/3.8/serializers-copiers.html