【问题标题】:Java serialization, Kryo and the object graphJava 序列化、Kryo 和对象图
【发布时间】:2012-09-16 12:26:27
【问题描述】:

假设我在内存中有一个 A 类型的对象数组 arr,每个对象都有一个指向同一对象 B 的引用字段。

插图:

A_1  A_2  A_3 ... A_N
 |    |    |       |
 |    |    V       |
 \--->\--> B <-----/

请注意,A 类型的每个对象中的引用字段都指向B 类型的相同 对象。

现在,我将包含A 类型对象的数组arr 序列化为ObjectOutputStream。然后我反序列化通过这种方式获得的字节。

我得到一个新数组arr1

1) 数组arr1 是否具有A 类型的对象,使得它们都指向B 类型的相同 对象? (我指的不是序列化前的同一个对象,而是一个新创建的独特的B类型的对象)

2) 换句话说,在 Java 中调用 serialize/deserialize 是否保留与序列化之前相同的对象图? (即新反序列化的对象图是否与旧对象图同构)

3) 这在哪里记录? (即请提供引用)

4) 相同的问题 1-3,但适用于 Java 的 Kryo 序列化框架。

谢谢。

【问题讨论】:

    标签: java serialization kryo


    【解决方案1】:

    http://docs.oracle.com/javase/6/docs/api/java/io/ObjectOutputStream.html

    对象的默认序列化机制写入的类 对象、类签名和所有非瞬态的值 和非静态字段。对其他对象的引用(除了在 瞬态或静态字段)导致这些对象也被写入。 对单个对象的多个引用使用引用进行编码 共享机制,以便对象的图可以恢复到 与原作时的形状相同。

    就我对规范的理解而言,如果要共享的对象实例通过相同的 ObjectOutputStream,您将获得共享对象引用。

    因此,当您序列化包含 arr 数组的类时,写入的每个对象都会获得一个 ID,并且对于通过流的每个引用,只会写入该 ID。在这种情况下,反序列化的图与原始图保持同质。

    很抱歉,我对 krio 库自己的序列化机制无能为力,我很乐意向同样使用它的人学习。

    关于 kryo 的编辑:

    我找到的一些文档:

    • 默认情况下,图形中对象在第一次出现之后的每次出现都存储为整数序数。这允许对同一对象和循环图的多个引用进行序列化。这会产生少量开销,如果不需要,可以禁用以节省空间:kryo.setReferences(false);

    • This(github)是引用解析器的合约;给出了两种实现:基于 ArrayList 的小对象图,基于 Map 的大对象

    • This 是默认对象数组(反)序列化器的实现

    • 需要注册类以进行(反)序列化;每个注册的类都可以加上一个序列化器(其中默认Java序列化mechanism

    【讨论】:

    • 通过同一个ObjectOutputStream,还是另外通过同一个writeObject方法调用?
    • 只是通过同一个流;想想两个相互引用的对象。您将第一个(以及对第二个的引用)写入流。然后,当您将第二个写入相同的流时,这两个流都有 ID,引用将被共享。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-16
    相关资源
    最近更新 更多