Java序列化-优点和缺点,使用还是避免?[关闭]


20

序列化用于Java的持久性。可以使用序列化持久化一些对象。但是,对于大量对象,ORM,数据库等可能会更好。似乎序列化仅对小型作业有用。可能是我错了。因此,请告诉我序列化比非序列化方法有什么优势?什么时候应该使用,什么时候应该避免使用?

看到DZone文章“对象序列化是否有害”之后,这个问题浮现在我脑海

以下是引起我疑问的内容:

如果您查看Java及其会话对象,则使用纯对象序列化。假设应用程序会话的寿命很短(最多几个小时),则对象序列化非常简单,得到了很好的支持,并内置在会话的Java概念中。但是,当数据持久性处于较长的时间段(可能是数天或数周)时,并且您不得不担心应用程序的新发行版时,序列化很快就会变成邪恶。正如任何优秀的Java开发人员所知道的那样,如果您打算序列化对象(即使在会话中),则需要一个真实的序列化ID(serialVersionUID),而不仅仅是1L,并且您需要实现Serializable接口。但是,大多数开发人员都不知道Java反序列化过程背后的实际规则。如果您的对象已更改,则不仅仅向对象添加简单字段,即使序列号未更改,Java也可能无法正确反序列化对象。突然,您无法再检索数据,这本质上是糟糕的。

现在,可能开发人员阅读此文章可能会说他们将永远不会编写有此问题的代码。可能是这样,但是您使用的库或公司不再雇用的其他开发人员呢?您能保证这个问题永远不会发生吗?保证的唯一方法是使用其他序列化方法。


您介意扩展一下引文中具体引起您问题的内容吗?
2013年

@gnat-将行添加到问题中。
刮板机

关于“不仅仅是一个1L”的部分是不正确的。
user207421

Answers:


15

序列化主要用于两个领域:

  • 持久性原型

    几乎每个对象图都可以快速变得可序列化,对于快速的概念验证或肮脏的应用程序,这可能比设置真实的ORM层或其他持久性系统要快

  • 短期存储几乎任意的对象:

    例如,应用程序服务器倾向于使用序列化来保留会话信息。这样做的好处是,会话中的值几乎可以是任何类型(只要其可序列化)。

对于几乎所有其他用途,您(和文章)提到的缺点太大:确切的格式很难保持稳定,类更改很容易使序列化数据不可读,用非Java代码读取/写入数据几乎不可能(或者至少比必要要难得多)。

JAXB和类似技术以类似的低成本提供了类似的功能,同时减少了一些问题。


我不会将JAXB称为“低成本”-必须编写模式。
凯文·克莱恩

3
@kevincline:您不需要使用JAXB的架构,它是完全可选的(如果愿意,您甚至可以从您的类中生成它)。另外:如果JAXB出于某种原因没有用,那么还有很多替代方法,例如XML Beans也可以。
Joachim Sauer 2013年

12

我使用对象序列化来进行事后分析,以防生产中出现意外错误。计算的输入被序列化到数据文件。如果报告了错误,则简单的程序可以重新加载输入,并使用附带的调试器重新运行计算。或者,可以使用普通的外壳来重新加载对象并根据需要修改它们。

我们还使用序列化将Java对象通过HTTP传递到Web服务。比序列化到文本和从文本序列化要容易得多。缺点是客户端和服务器安装必须一起部署,但这不是问题,因为我们可以控制两端。


3
那是一个有趣的用例!太小了,无法使用“更复杂”的系统,并且大多数缺点都不适用!
Joachim Sauer 2013年

现在,我们已经编写了事后分析器,该分析器使用POI从Java对象构建电子表格,以便于查看。这为我们节省了许多时间的日志文件检查。
凯文·克莱恩

7

与非序列化方法相比,序列化有哪些优势?

Java序列化具有一些优点:

  • 内置于系统中:您无需依赖第三方工具,库或配置。

  • 至少在开始时相对简单易懂

  • 每个开发人员都知道(或应该知道)。无论Java开发人员赞成还是反对,他们都可能熟悉序列化Java对象。

而且,当然也有缺点:

  • 规避标准Java流程。 分配内存但不调用构造函数,因此不会初始化临时字段。字段以字母顺序而不是源顺序初始化。

  • 就空间而言,效率不高,但也不可怕。您可能要压缩结果。

  • 易碎,除非在更换对象时采取预防措施。即使如此。

什么时候应该使用,什么时候应该避免使用?

以下情况下使用

  • 部署规模很重要。内置于系统中,因此额外增加了0个字节。

  • 所有演员将使用兼容版本。

  • 长期存储不是问题。

避免在以下情况下使用

  • 以上任何一项都不适用。

3

序列化和ORM /数据库是不同的东西,尽管存在一些重叠。

序列化的对象表示“解冻”持久对象并重新填充其数据所需的所有信息。ORM和数据库将数据持久保存到数据库中。一个类可以具有ORM未存储在数据库中的信息字段,例如,计算字段。

此外,序列化和ORM正在解决不同的问题。序列化解决了将对象图持久化到流(内存,文件系统等)的问题。除了提供诸如搜索和延迟加载之类的功能外,ORM还处理信息到数据库列的映射以及对象的检索和实例化。

当您要将数据持久保存到数据库中时,如果您要处理大量数据或需要报告,搜索/查询,仓储或其他数据库擅长的事情,请使用ORM。当您要将数据结构的表示形式保存到光盘时,请使用序列化。


0

序列化在实践中很少使用。

如前所述,序列化最常见的用例是将对象作为Blob存储在会话数据库中。这很好地工作有两个原因:会话往往是短暂的,并且会话数据库如何不知道如何将任意对象映射到关系模型。

对于需要长时间保留的数据(例如Amazon购物车),最佳实践是将这些数据存储在数据库中。

会话持久性机制可确保具有活动会话的用户返回到同一服务器。仅当服务器发生故障并且用户被重定向到新服务器时,才访问会话数据库。新服务器检测到活动的会话,但未在内存中找到它,因此它尝试从会话数据库中检索它,以尝试向用户提供无缝体验。

这种方法有两个问题:

首先,将会话数据刷新到会话数据库是一个缓慢的过程。刷新会话数据经常会降低性能,大多数服务器都配置为每30秒,每分钟或更长时间刷新一次。这种“无缝”故障转移解决方案永远不会100%有效。

其次,我的经验是,大多数客户都同意抛出一条错误消息,要求用户登录并在极少数服务器发生故障的情况下重试。在这种情况下,我们将完全关闭会话数据库,并享受性能提升。

序列化的另一种用途是通过使用诸如Flex之类的框架来提供更快的响应时间,该框架使用序列化和对象图的压缩进行服务器-客户端交互。

正如其他人指出的那样,采用序列化有一些创造性和有用的理由,但是在实践中很少见。

从历史上看,序列化很难正确实现,并且可靠性很高,因此只能在少数情况下使用。大多数开发人员永远不会自己序列化对象,而是可能依赖幕后进行操作的框架。


2
“串行化实际上很少使用。” - 在REST Web服务的世界中经常称为序列化。在大多数情况下,仅处理Strings和Integers之类的东西-但是它是真实的东西,更复杂的对象需要对此有所了解。说很少使用它会忽略大量频繁使用它的域。

0

“何时使用Java序列化”和“何时避免Java序列化”的简短答案

如果使用Java序列化

  • 几乎不需要编码
  • 二进制数据不是人类可读的都没关系
  • 无需搜索序列化数据(不可能进行类似数据库的查询)
  • 要么
    • 序列化的数据结构不变或
    • 在“数据结构更改”后是否不再可读存储的序列化数据(即Web应用程序中的会话数据)没关系

在所有其他情况下,“二进制Java序列化”都是不好的

备择方案

  • xml序列化
  • Nosql数据库
  • ORM关系数据库
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.