Главная страница
Навигация по странице:

  • Листинг 4.

  • Листинг 5.

  • Алгоритм сериализации Java

  • Листинг 6.

  • Листинг 7.

  • Рисунок 2.

  • Листинг 8.

  • Ответы на вопросы по ревью 4. Java io. Ключевым понятием здесь является понятие потока


    Скачать 1.93 Mb.
    НазваниеJava io. Ключевым понятием здесь является понятие потока
    Дата03.07.2022
    Размер1.93 Mb.
    Формат файлаdoc
    Имя файлаОтветы на вопросы по ревью 4.doc
    ТипДокументы
    #623608
    страница19 из 39
    1   ...   15   16   17   18   19   20   21   22   ...   39

    Формат сериализованного объекта



    Как должен выглядеть сериализованный объект? Вспомните простой код из предыдущего раздела, который сериализует объект класса TestSerial и записывает в temp.out. В листинге 4 показано содержимое файла temp.out, в шестнадцатеричном виде.

    Листинг 4.

    AC ED 00 05 73 72 00 0A 53 65 72 69 61 6C 54 65
    73 74 A0 0C 34 00 FE B1 DD F9 02 00 02 42 00 05
    63 6F 75 6E 74 42 00 07 76 65 72 73 69 6F 6E 78
    70 00 64


    Если вы снова посмотрите на TestSerial, то увидите, что у него всего 2 байтовых члена. Как показано в листинге 5.

    Листинг 5.

      public byte version = 100;
      public byte count = 0;

    * This source code was highlighted with Source Code Highlighter.


    Размер байтовой переменной один байт, и следовательно полный размер объекта (без заголовка) — два байта. Но размер сериализованного объекта 51 байт. Удивлены? Откуда взялись эти дополнительные байты и что они обозначают? Они добавлены сериализующим алгоритмом и необходимы для воссоздания объекта. В следующем абзаце будет подробно описан этот алгоритм.

    Алгоритм сериализации Java



    К этому моменту у вас уже должно быть достаточно знаний, чтобы сериализовать объект. Но как работает этот механизм? Алгоритм сериализации делает следующие вещи:




    В листинге 6 указан пример охватывающий все возможные случаи сериализации

    Листинг 6.

    class parent implements Serializable {
      int parentVersion = 10;
    }

    class contain implements Serializable{
      int containVersion = 11;
    }
    public class SerialTest extends parent implements Serializable {
      int version = 66;
      contain con = new contain();

      public int getVersion() {
        return version;
      }
      public static void main(String args[]) throws IOException {
        FileOutputStream fos = new FileOutputStream("temp.out");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        SerialTest st = new SerialTest();
        oos.writeObject(st);
        oos.flush();
        oos.close();
      }
    }

    * This source code was highlighted with Source Code Highlighter.

    В примере сериализуется объект класса SerialTest, который наследуется от parent и содержит объект-контейнер классаcontain. В листинге 7 показан сериализованный объект.

    Листинг 7.

    AC ED 00 05 73 72 00 0A 53 65 72 69 61 6C 54 65
    73 74 05 52 81 5A AC 66 02 F6 02 00 02 49 00 07
    76 65 72 73 69 6F 6E 4C 00 03 63 6F 6E 74 00 09
    4C 63 6F 6E 74 61 69 6E 3B 78 72 00 06 70 61 72
    65 6E 74 0E DB D2 BD 85 EE 63 7A 02 00 01 49 00
    0D 70 61 72 65 6E 74 56 65 72 73 69 6F 6E 78 70
    00 00 00 0A 00 00 00 42 73 72 00 07 63 6F 6E 74
    61 69 6E FC BB E6 0E FB CB 60 C7 02 00 01 49 00
    0E 63 6F 6E 74 61 69 6E 56 65 72 73 69 6F 6E 78
    70 00 00 00 0B


    На рисунке 2 показан сценарий алгоритма сериализации.
    ðŸñ€ñð¼ð¾ñƒð³ð¾ð»ñŒð½ð¸ðº 10
    Рисунок 2.

    Давайте рассмотрим, что собой представляет каждый байт в сериализованном объекте. В начале идёт информация о протоколе сериализации:



    • AC ED: STREAM_MAGIC. Говорит о том, что используется протокол сериазизации.

    • 00 05: STREAM_VERSION. Версия сериализации.

    • 0x73: TC_OBJECT. Обозначение нового объекта.


    На первом шаге алгоритм сериализации записывает описание класса ассоциированного с объектом. В примере был сериализован объект класса SerialTest, следовательно алгоритм начал записывать описание класса SerailTest.



    • 0x72: TC_CLASSDESC. Обозначение нового класса.

    • 00 0A: Длина имени класса.

    • 53 65 72 69 61 6c 54 65 73 74: SerialTest, имя класса.

    • 05 52 81 5A AC 66 02 F6: SerialVersionUID, идентификатор класса.

    • 0x02: Различные флаги. Этот специфический флаг говорит о том, что объект поддерживает сериализацию.

    • 00 02: Число полей в классе.


    Теперь алгоритм записывает поле int version = 66;.



    • 0x49: Код типа поля. 49 это «I», которое закреплено за Int.

    • 00 07: Длина имени поля.

    • 76 65 72 73 69 6F 6E: version, имя поля.


    Затем алгоритм записывает следующее поле, contain con = new contain();. Это объект следовательно будет записано каноническое JVM обозначение этого поля.



    • 0x74: TC_STRING. Обозначает новую строку.

    • 00 09: Длина строки.

    • 4C 63 6F 6E 74 61 69 6E 3B: Lcontain;, Каноническое JVM обозначаение.

    • 0x78: TC_ENDBLOCKDATA, Конец опционального блока данных для объекта.


    Следующим шагом алгоритма является запись описания класса parent, который является непосредственным суперклассом для SerialTest.



    • 0x72: TC_CLASSDESC. Обозначение нового класса.

    • 00 06: Длина имени класса.

    • 70 61 72 65 6E 74: parent, имя класса

    • 0E DB D2 BD 85 EE 63 7A: SerialVersionUID, идентификатор класса.

    • 0x02: Различные флаги. Этот флаг обозначает что класс поддерживает сериализацию.

    • 00 01: Число полей в классе.


    Теперь алгоритм записывает описание полей класса parent, класс имеет одно полеint parentVersion = 100;.



    • 0x49: Код типа поля. 49 обозначает «I», которое закреплено за Int.

    • 00 0D: Длина имени поля.

    • 70 61 72 65 6E 74 56 65 72 73 69 6F 6E: parentVersion, имя поля.

    • 0x78: TC_ENDBLOCKDATA, конец опционального блока данных для объекта.

    • 0x70: TC_NULL, обозначает то что больше нет суперклассов, потому что мы достигли верха иерархии классов.


    До этого алгоритм сериализации записывал описание классов ассоциированных с объектом и всех его суперклассов. Теперь будут записаны фактические данные ассоциированные с объектом. Сначала записываются члены класса parent:



    • 00 00 00 0A: 10, Значение parentVersion.


    Дальше перемещаемся в SerialTest



    • 00 00 00 42: 66, Значение version.


    Следующие несколько байт очень интересны. Алгоритму необходимо записать информацию объекте класса contain.

    Листинг 8.

    contain con = new contain();

    * This source code was highlighted with Source Code Highlighter.


    Алгоритм сериализации ещё не записал описание класса contain. Настал момент это сделать.



    • 0x73: TC_OBJECT, обозначает новый объект.

    • 0x72: TC_CLASSDESC, обозначает новый класс.

    • 00 07: Длина имени класса.

    • 63 6F 6E 74 61 69 6E: contain, имя класса.

    • FC BB E6 0E FB CB 60 C7: SerialVersionUID, идентификатор этого класса.

    • 0x02: Различные флаги. Этот флаг обозначает что класс поддерживает сериализацию.

    • 00 01: Число полей в классе.


    Алгоритм должен записать описание единственного поля класса conatin, int containVersion = 11;.



    • 0x49: Код типа поля. 49 обозначает «I», которое закреплено за Int.

    • 00 0E: Длина имени поля.

    • 63 6F 6E 74 61 69 6E 56 65 72 73 69 6F 6E: containVersion, имя поля.

    • 0x78: TC_ENDBLOCKDATA, конец опционального блока данных для объекта.


    Дальше алгоритм проверяет, имеет ли contain родительский класс. Если имеет, то алгоритм начинает запись этого класса; но в нашем случае суперкласса у contain нету, и алгоритм записывает TC_NULL.



    • 0x70: TC_NULL


    В конце алгоритм записывает фактические данные ассоциированные с объектом класса conatin.



    • 00 00 00 0B: 11, значение containVersion.


    1   ...   15   16   17   18   19   20   21   22   ...   39


    написать администратору сайта