Сериализация Java, Kryo и граф объектов

Допустим, у меня есть массив arr объектов типа A в памяти, каждый из которых имеет поле ссылки, указывающее на один и тот же объект B.

Иллюстрация:

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

Обратите внимание, что поле ссылки в каждом объекте типа A указывает на один и тот же объект типа B.

Теперь я сериализую массив arr, содержащий объекты типа A, в массив ObjectOutputStream. Затем я десериализую полученные таким образом байты.

Я получаю новый массив arr1.

1) Есть ли в массиве arr1 объекты типа A, все они указывают на один и тот же объект типа B? (Я имею в виду не тот же объект до сериализации, а уникальный вновь созданный объект типа B)

2) Другими словами, сохраняет ли вызов сериализации/десериализации в Java тот же граф объектов, что и до сериализации? (т.е. является ли вновь десериализованный граф объектов изоморфным старому)

3) Где это зафиксировано? (т.е., пожалуйста, укажите цитату)

4) Те же вопросы 1–3, но применительно к структуре сериализации Kryo для сериализации Java.

Спасибо.


person axel22    schedule 16.09.2012    source источник


Ответы (1)


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

Механизм сериализации по умолчанию для объекта записывает класс объекта, сигнатуру класса и значения всех непереходных и нестатических полей. Ссылки на другие объекты (за исключением временных или статических полей) также вызывают запись этих объектов. Множественные ссылки на один объект кодируются с использованием механизма совместного использования ссылок, поэтому графы объектов могут быть восстановлены в той же форме, что и оригинал.

Что касается моего понимания спецификации, вы получаете ссылки на общие объекты, если экземпляры объектов, которые должны быть общими, проходят через один и тот же ObjectOutputStream.

Таким образом, когда вы сериализуете класс, содержащий массив arr, каждый записываемый объект получает идентификатор, и для каждой ссылки, проходящей через поток, записывается только этот идентификатор. Десериализованный граф в этом случае остается однородным с исходным графом.

Извините, но я не могу помочь с собственным механизмом сериализации библиотеки krio, я был бы очень рад узнать об этом от того, кто его использовал.

РЕДАКТИРОВАТЬ о крио:

Некоторая документация, которую я нашел:

  • По умолчанию каждое появление объекта на графике после первого сохраняется как целочисленный порядковый номер. Это позволяет сериализовать несколько ссылок на один и тот же объект и циклические графики. Это имеет небольшие накладные расходы и может быть отключено для экономии места, если оно не требуется: kryo.setReferences(false);

  • Это (github) — контракт резолвера ссылок; даны две реализации: на основе ArrayList для графов небольших объектов, на основе Map для более крупных

  • Это реализация массива объектов по умолчанию (де)сериализатор

  • Классы должны быть зарегистрированы для (де)сериализации; каждый зарегистрированный класс может быть связан с сериализатором (среди которых сериализация Java по умолчанию механизм)

person guido    schedule 16.09.2012
comment
Через тот же ObjectOutputStream или дополнительно через тот же вызов метода writeObject? - person axel22; 16.09.2012
comment
Просто через тот же поток; подумайте о двух объектах, ссылающихся друг на друга. Вы записываете первое (и, следовательно, ссылку на второе) в поток. Когда вы затем записываете второй в тот же поток, который имеет идентификаторы для обоих, ссылки становятся общими. - person guido; 16.09.2012