哪个是Java序列化的最佳替代方案?

问题描述 投票:45回答:13

我目前正在开发一个项目,它需要持久保存任何类型的对象(我们没有任何控制的实现),因此这些对象可以在之后恢复。

我们无法实现ORM,因为我们无法在开发时限制库的用户。

我们的第一个选择是使用Java默认序列化对其进行序列化,但是当用户开始传递同一对象的不同版本(属性更改类型,名称,...)时,我们在恢复对象时遇到了很多麻烦。

我们尝试过使用XMLEncoder类(将对象转换为XML),但我们发现缺少功能(例如,不支持Enums)。

最后,我们还尝试了JAXB,但这会强制我们的用户注释他们的类。

还有什么好办法吗

java serialization xml-serialization
13个回答
9
投票

你要做的最简单的事情仍然是使用序列化,IMO,但更多地考虑类的序列化形式(无论如何你应该做的)。例如:

  1. 明确定义SerialUID。
  2. 在适当的地方定义您自己的序列化表格。

序列化表单是API类的一部分,应仔细考虑其设计。

我不会详细介绍,因为我所说的几乎所有内容都来自Effective Java。我会转而推荐你,特别是有关序列化的章节。它会警告您遇到的所有问题,并为问题提供正确的解决方案:

http://www.amazon.com/Effective-Java-2nd-Joshua-Bloch/dp/0321356683


话虽如此,如果您仍在考虑非序列化方法,这里有几个:

XML编组

正如许多人所指出的那样是一种选择,但我认为你仍然会遇到向后兼容性问题。但是,使用XML编组,您可能会立即捕获这些内容,因为某些框架可能会在初始化期间为您进行一些检查。

转换到/来自YAML

这是我一直在想的一个想法,但我真的很喜欢YAML格式(至少作为自定义toString()格式)。但实际上,唯一不同的是你要编组YAML而不是XML。唯一的好处是YAML比XML更具人性化。同样的限制适用。


1
投票

可能Castor


1
投票

Betwixt是一个很好的用于序列化对象的库 - 但它不会是一种自动的东西。如果您必须序列化的对象数量相对固定,这对您来说可能是一个不错的选择,但如果您的“客户”将一直向您抛出新课程,则可能需要付出更多努力(对于所有特殊情况,绝对比XMLEncoder更容易。

另一种方法是要求您的客户为他们抛出的任何对象提供适当的.betwixt文件(这有效地将责任转移给他们)。

长期和短期 - 序列化很难 - 没有完全脑死亡的方法。 Java序列化与我所见过的脑死亡解决方案非常接近,但正如您所发现的,不正确使用版本的uid值可能会破坏它。 Java序列化还需要使用标记'Serializable'接口,所以如果你无法控制你的源代码,那你就有点不幸了。

如果要求真的像你描述的那样艰巨,你可能不得不在对象/方面/其他方面采用某种BCE(字节代码修改)。这远远超出了小型开发项目的范围,进入了Hibernate,Casper或ORM ......


0
投票

另一个想法:使用缓存。缓存为应用程序提供了更好的控制,可伸缩性和健壮性。但仍需要序列化,但在缓存服务框架内管理变得更容易。缓存可以保存在内存,磁盘,数据库或阵列中 - 或者所有选项中 - 其中一个是溢出,待机,另一个是故障转移。 Commons JCS和Ehcache是​​两个java实现,后者是一个免费存储高达32 GB的企业解决方案(免责声明:我不适用于ehcache ;-))。


0
投票

SBE是一个用于快速,基于字节缓冲的序列化库并且能够进行版本控制的已建立的库。但是,由于需要在其上编写长度包装类,因此使用起来有点困难。

鉴于它的缺点,我最近创建了一个仅受Java限制的序列化库,受到SBE和FIX协议(用于交换交易/报价消息的通用金融市场协议)的启发,试图在克服弱点的同时保持两者的优势。你可以看看https://github.com/iceberglet/anymsg


39
投票

这是2011年,在商业级REST Web服务项目中,我们使用以下序列化器为客户提供各种媒体类型:

  • XStream(用于XML但不用于JSON)
  • Jackson(适用于JSON)
  • Kryo(一种快速,紧凑的二进制序列化格式)
  • Smile(Jackson 1.6及更高版本附带的二进制格式)。
  • Java对象序列化。

我们最近尝试了其他序列化程序:

  • SimpleXML看起来很稳固,运行速度是XStream的2倍,但是对于我们的情况需要一点点配置。
  • YamlBeans有几个错误。
  • SnakeYAML有一个与日期有关的小错误。

杰克逊JSON,Kryo和杰克逊微笑都比旧的Java对象序列化快得多,大约3倍到4.5倍。 XStream很慢。但在这一点上,这些都是可靠的选择。我们将继续监控其他三个。


19
投票

http://x-stream.github.io/很好,请看看它!很方便


14
投票

其实施我们没有任何控制权

解决方案是不要这样做。如果您无法控制类型的实现,则不应将其序列化。故事结局。 Java序列化提供了serialVersionUID,专门用于管理不同版本的类型之间的序列化不兼容性。如果您不控制实现,则在开发人员更改类时无法确定ID是否正确更改。

举一个'点'的简单例子。它可以用笛卡尔坐标系或极坐标系表示。构建一个可以动态应对这些修正的系统将是成本过高的 - 它实际上必须是设计序列化的类的开发人员。

简而言之,这是你的设计错了 - 而不是技术。


9
投票

谷歌提出了一个二进制协议 - http://code.google.com/apis/protocolbuffers/速度更快,与XML相比具有更小的有效载荷 - 其他人建议将其作为替代协议。

协议缓冲区的一个优点是它可以与C,C ++,python和java交换信息。


5
投票

例如,尝试使用Gson序列化为json。


5
投票

也是一个非常快速的JDK序列化替代品:http://ruedigermoeller.github.io/fast-serialization/


3
投票

如果序列化速度对您很重要,那么这里有一个全面的JVM序列化基准测试:


1
投票

就个人而言,我使用Fame很多,因为它具有与Smalltalk(包括VW和Squeak)和Python的互操作性。 (免责声明,我是Fame项目的主要贡献者。)

© www.soinside.com 2019 - 2024. All rights reserved.