【问题标题】:efficient java object graph serialization高效的java对象图序列化
【发布时间】:2010-10-17 13:19:27
【问题描述】:

序列化 java 对象图的最佳方法是什么?

我对序列化库的要求是 1)反序列化速度 2) 大小 - 尽可能小(小于 java 默认序列化) 3) 灵活性——基于注释的定义什么必须被序列化会很好。

底层文件格式并不重要。

我看了Protocol Buffers和XStream,但前者不够灵活,因为需要映射文件,而后者产生大文件。

任何帮助表示赞赏。

【问题讨论】:

  • JVM 序列化程序的比较 (github.com/eishay/jvm-serializers/wiki) 提供了有关性能和序列化结果大小的有用信息。它只涵盖了一个用例(一种类型的序列化对象),但给出了一些想法。

标签: java serialization


【解决方案1】:

对于小对象,Java序列化形式很可能以序列化类的描述为主。

您可以为常用类写出序列化数据,然后将其用作一系列序列化流的公共前缀。请注意,这是非常脆弱的,您可能需要重新计算并检查每个类加载器实例。

【讨论】:

    【解决方案2】:

    对于序列化,Hessian 是最有效的方法之一。

    这比 Java 序列化小 2-3 倍,速度快,即使使用 Externalizable 类也是如此。

    无论您使用哪种序列化,都可以相当轻松地使用压缩来使数据更加紧凑。

    除此之外,您还可以编写自己的序列化。我写了一个序列化程序,它写入/写入 ByteBuffer 的速度大约是 Hessian 的两倍,大小是 Hessian 的一半(大约比 Java 序列化快 5 倍/小)如果现有的序列化可以满足您的需要,这可能会付出太多努力而收效甚微。但是,它可以随心所欲地定制;)

    【讨论】:

    • 你写了什么样的序列化器?它适用于任何对象,还是您需要为每个类编写自定义序列化代码?是否允许循环对象引用?
    • 很像Hessian。它可以序列化任何对象,除了那些对 Java 之外的真实资源建模的对象,如线程、套接字等。你可以编写自定义序列化,但由于它使用一些智能的动态压缩,自定义序列化器会变得更慢!
    • "是否允许循环对象引用?" - 有一个不支持这个的开源版本,我为工作写了另一个版本。 ;)
    【解决方案3】:

    我支持关于压缩有用性的说明 - 所有格式压缩到大致相同,即更大的输出压缩更多。

    除此之外和其他建议之外,带有Jackson 的 JSON 效果很好:比 XML 快得多(与 PB、Hessian 竞争)并且更紧凑;比 PB 灵活得多,易于与客户端 JS 集成(如果重要的话)并且易于排除故障。

    【讨论】:

    【解决方案4】:

    我认为默认的 Java 序列化会非常小。您不能通过transient 关键字有效地限制您想要序列化的内容吗?这将解决您的第三个问题(灵活性和注释)

    【讨论】:

    • 默认序列化对于单个对象来说通常是巨大的。这是因为它包含所有类元数据;对于具有多个相同类型实例的较大对象图,这不是一个问题(只是一个类定义),但对于单个对象,它很不幸很重要。
    【解决方案5】:

    您可以使用Databoard 进行递归序列化。

    它看起来像这样..

    @Referable class Node {
        public int id;
        public Node[] reference;
        public Node(int id, Node...reference) {
            this.id = id;
            this.reference = reference;
        }
    
    }
    
    public static void main(String[] args) throws Exception {
    
        Node a = new Node(0);
        Node b = new Node(1);
        Node c = new Node(2);
        a.reference = new Node[] {b, c};
        b.reference = new Node[] {a};
        c.reference = new Node[] {c};
    
        Binding binding = Bindings.getBinding( Node.class );
        Serializer s = binding.serializer();
        byte[] data = s.serialize(a);
    
        Node d = (Node) s.deserialize( data );
        System.out.println( binding.toString(d) );
    }
    

    【讨论】:

      【解决方案6】:

      http://jserial.sourceforge.net/ 会满足您的需求吗?

      【讨论】:

      • 从他们的基准测试结果来看,“Bubble”反序列化比普通的 Java 1.4.2 序列化
      • 在其中两个基准测试中速度较慢,在其他基准测试中速度更快。这取决于正在序列化的内容,并且无论如何 1.4.2 是古老的,因此您应该使用自己的应用程序和环境对其进行基准测试,看看它是否适合您。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-17
      相关资源
      最近更新 更多