【问题标题】:Which is the best alternative for Java Serialization?哪个是 Java 序列化的最佳替代方案?
【发布时间】:2010-09-19 08:25:36
【问题描述】:

我目前正在开展一个项目,该项目需要保留任何类型的对象(我们无法控制其实现),以便之后可以恢复这些对象。

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

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

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

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

有什么好的选择吗?

【问题讨论】:

  • db4o.com ?一个开源的面向对象的数据库
  • @Ande Turner - Ande,也许你可以在下面添加这个作为答案。无法在 cmets 上投票等 :-)

标签: java serialization xml-serialization


【解决方案1】:

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

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

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

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

Jackson JSON、Kryo 和 Jackson Smile 都比旧的 Java 对象序列化快得多,大约快 3 到 4.5 倍。 XStream 速度较慢。但在这一点上,这些都是可靠的选择。我们将继续监视其他三个。

【讨论】:

  • 非常好的序列化程序集——关于我唯一可能提到的另一个是protostuff。另外:Jackson 现在有 XML 模块 (github.com/FasterXML/jackson-dataformat-xml),它可以很好地作为 XStream 的潜在替代品;在运行良好的地方要快得多。如果需要 YAML 输出,甚至还有 YAML 插件(github.com/FasterXML/jackson-dataformat-yaml);这些都使用相同的数据绑定,只是不同的低级解析器/生成器。
  • 我会选择 SimpleXML。它是高度可定制的,并通过简单的逻辑注释为您提供所需的一切。
  • 我与 Jackson 的作者合作多年,他的工作非常出色(快速响应,可靠的代码库)。我会为他从事的任何项目做担保(所以我建议你试试 Smile)。
  • Kyro 绝对摇滚!我喜欢二进制格式(不知道为什么!):D
【解决方案2】:

http://x-stream.github.io/不错,请看一下!很方便

【讨论】:

  • 唯一的问题是它不擅长处理模式/类的变化。
【解决方案3】:

我们无法控制哪些实现

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

以“点”为例。它可以用笛卡尔坐标系或极坐标系来表示。构建一个可以动态处理这些修正的系统的成本太高了——实际上必须是设计序列化的类的开发人员。

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

【讨论】:

  • 我不认为这不是完美的解决方案,但无论如何这是对我的外部要求。我们正在开发一个库,有必要通过这个库注册调用。
  • 不同意。使用 fst-serialization 您可以选择注入序列化代码,即使是您无法控制的类(序列化程序类)。显式版本控制也不是问题,只是JDK方法没有那么好..
【解决方案4】:

对你来说最简单的事情仍然是使用序列化,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 更易于阅读。同样的限制也适用。

【讨论】:

    【解决方案5】:

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

    protocol buffers 的优点之一是它可以与 C、C++、python 和 java 交换信息。

    【讨论】:

    • 不幸的是,您不能真正将它用于任意 POJO,因为您 (a) 需要每种类型的模式,并且 (b) 必须使用代码生成对象。
    • 除此之外,Protocol Buffers 不是为可能的循环引用或对象共享而设计的(尽管这可能会被入侵,就像 JSync 概念 (jsync.org) 将对象引用添加到 JSON 一样)
    【解决方案6】:

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

    【讨论】:

      【解决方案7】:

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

      【讨论】:

      • 不支持任何Java新版本,不支持8以上
      【解决方案8】:

      如果序列化速度对您很重要,那么这里有一个 JVM 序列化程序的综合基准:

      【讨论】:

        【解决方案9】:

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

        【讨论】:

          【解决方案10】:

          可能是Castor

          【讨论】:

          • JiBX 是一个绑定工具,而不是序列化工具。
          【解决方案11】:

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

          另一种方法是要求您的客户为他们扔给您的任何对象提供适当的 .betwixt 文件(这实际上将责任转移给了他们)。

          长短 - 序列化是困难 - 没有完全脑死的方法。 Java 序列化是我所见过的最接近脑死的解决方案,但正如您所发现的,不正确地使用版本 uid 值可能会破坏它。 Java 序列化还需要使用标记“Serializable”接口,所以如果你不能控制你的源代码,那你就有点不走运了。

          如果要求确实像您描述的那样艰巨,您可能不得不对对象/方面/其他方面采取某种 BCE(字节码修改)。这已经超出了小型开发项目的领域,进入了 Hibernate、Casper 或 ORM 的领域......

          【讨论】:

            【解决方案12】:

            SBE 是一个成熟的库,用于快速、基于字节缓冲区的序列化库,并且能够进行版本控制。但是它有点难以使用,因为您需要在其上编写长度包装类。

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

            【讨论】:

              【解决方案13】:

              另一个想法:使用缓存。缓存为应用程序提供了更好的控制、可扩展性和健壮性。尽管如此,仍然需要序列化,但是在缓存服务框架内管理变得更加容易。缓存可以保存在内存、磁盘、数据库或阵列中——或所有选项中——其中一个是溢出、备用、故障转移。 Commons JCS 和 Ehcache 是两个 java 实现,后者是一个企业解决方案,最多可释放 32 GB 的存储空间(免责声明:我不为 ehcache 工作;-))。

              【讨论】:

                猜你喜欢
                • 2011-02-02
                • 2017-06-11
                • 1970-01-01
                • 2010-12-07
                • 1970-01-01
                • 2021-01-17
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多