Сериализация и десериализация
Сериализация — это процесс преобразования объектов, хранящихся в памяти, в форму, которую можно использовать для постоянного хранения или связи с помощью некоторого алгоритма.
Десериализация — это процесс восстановления постоянно хранимых или передаваемых данных в объекты с помощью соответствующего алгоритма синтаксического анализа, это операция, обратная сериализации.
Зачем нужна сериализация
Когда клиентская часть запрашивает данные из внутреннего интерфейса, серверная часть должна возвращать данные JSON, то есть серверная часть сериализует объекты в куче Java в данные JSON и передает их во внешний интерфейс. Внешний интерфейс может использовать его напрямую или десериализовать в JS в соответствии со своими потребностями.
В процессе удаленного вызова RPC вызывающий и вызываемый должны согласовать алгоритмы сериализации и десериализации.Например, приложение A сериализует объект User в данные JSON и передает их приложению B. Данные объекта пользователя:{"id": 1, "name": "long"}
, при достижении приложения B эти данные необходимо десериализовать в объекты.Если алгоритм десериализации приложения B в это время является XML, синтаксический анализ должен завершиться неудачей, поэтому необходимо согласовать, что все они используют алгоритм сериализации JSON.Затем объект User может быть успешно проанализирован на основе стандарта JSON
Сериализация в Java
transient
Если поле, которое мы не хотим выводить через механизм сериализации Java по умолчанию, мы можем использовать это поле, чтобы указать, что текущее поле не нужно сериализовать.
записьОбъект и чтениеОбъект
Мы хотим сериализовать адресные данные нестандартным способом.
Среди них writeObject будет рефлексивно вызывать этот метод при записи сериализованных данных, а readObject будет вызывать его при десериализации.
Роль serialVersionUID
Если мы не настроим serialVersionUID, он будет автоматически сгенерирован в соответствии с информацией текущего класса. Если текущий класс не изменен, сгенерированный serialVersionUID будет таким же. Если serialVersionUID изменен, serialVersionUID изменится и не может быть десериализованным. Обязательно заполните это поле
Принцип реализации сериализации Java
При первом взгляде на код не цепляйтесь сразу за все детали, нужно смотреть только те моменты, которые нас сейчас волнуют, а потом уже смотреть на некоторые детали, когда понимание постепенно углубляется, иначе все просто. выглядеть озадаченным.
первый звонокobjectOutputStream.writeObject(user);
тогда позвониwriteObject0(obj, false);
В этом методе есть такой кусок кода
Во-первых, напишите флаг объекта TC_Object в поток, указывая на то, что данные, которые в настоящее время записаны, является объектом, а затем вызовите writeserialData, чтобы начать запись конкретных данных
-
Во-первых, мы получим классдатаслот. Мы можем думать об этом как об этом в качестве вспомогательного метода, который обеспечивает сериализованные объекты.
-
Здесь используйте ClassDataSlot, чтобы проверить, реализован ли метод writeObject в сериализованном объекте.Когда инициализируется этот метод writeObjectMethod? я скоро расскажу об этом
-
Если writeObject реализован, мы будем вызывать метод рефлексивно.
-
Если текущий класс не реализует метод writeObject, вызовите метод defaultWriteFields по умолчанию для записи данных.
Как узнать, реализует ли объект writeObject(ObjectOutputStream out) и readObject
В приведенном выше мы знаем, что он оценивается writeObjectMethod, поэтому, где это поле инициализировано, мы возвращаемся к методу writeObject0 ObjectOutputStream, и есть такой кусок кода перед вызовом последующего метода writeOrderinaryObject.
Затем мы возвращаемся к defaultWriteFields(Object obj, ObjectStreamClass desc), чтобы продолжить.
- Получить конкретную длину текущих данных для записи
- Чтобы получить значение текущих данных посредством отражения, объект desc ObjectStreamClass может быть Object или базовым типом и т. д. В это время получается объект User, поэтому полученное значение по умолчанию пусто, потому что только его определенные поля здесь написаны данные
- Получить все значения текущего объекта через отражение
- Вызовите writeObject0 один за другим, чтобы записать определенные значения. Первый вызов — Integer. Поскольку это класс-оболочка, Integer наследует Number, а класс Number реализует Serializable, поэтому он будет следовать тому же процессу, что и объект User.
- Затем он вступает в запись String, снова вызывает writeObject0 и достигает writeObject0 из ObjectOutputStream, который позже отличается, потому что здесь записан конкретный тип String.
Наконец, давайте посмотрим, сколько байт занято после сериализации
Принцип десериализации Java
Десериализация это фактически обратный процесс сериализации.Если вы понимаете код ключа сериализации, то увидеть этот процесс не составит труда.Код ключа выложен ниже для анализа.
Здесь вы можете видеть, что различная обработка будет выполняться в соответствии с конкретным типом десериализованного объекта.Наш текущий объект — это объект пользователя, поэтому он войдет в метод, указанный стрелкой.
- Получить длину данных текущего входящего объекта. Поскольку входящий объект пользователя пустой, в настоящее время длина пуста.
- Отражение получает все поля, которые необходимо десериализовать, и создает соответствующий массив для сохранения соответствующих значений.В это время полученный объект пользователя имеет 2 поля: идентификатор и имя
- Затем начните рекурсивно вызывать readObject0 для обработки всех полей, которые необходимо десериализовать, возьмите текущий идентификатор и имя в качестве примера.
- Как и в приведенной выше сериализации, id является классом-оболочкой Integer, поэтому он будет распознан как Object.Когда этот метод будет достигнут снова, на первом этапе primDataSize Длина данных равна 4, поскольку это тип int из 4 байтов.
- На втором этапе, поскольку у Integer нет других полей, которые необходимо десериализовать, у него есть только собственное неупакованное значение, поэтому он дойдет до четвертого шага, чтобы установить значение текущего идентификатора.
- Установить значение поля текущего базового типа
Для типа String вызовет чтение соответствующего значения в первой десериализации.
Другие методы сериализации
Рождение новой технологии имеет определенные причины и предпосылки: например, объем данных после нативной сериализации в Java относительно велик, эффективность передачи низкая, и в то же время межъязыковая коммуникация невозможна, поэтому многие выбирают используйте XML для сериализации данных. , XML-сериализация решает проблему межъязыковой связи, но сериализованные данные больше, чем исходные данные, поэтому родилась сериализация JSON, которая поддерживает кросс-язык, а сериализованные данные намного меньше, чем первые 2, и, наконец, кто-то захотел еще больше оптимизировать размер и представил Protobuf, которыйкомпрессияфункция, сжатые данные меньше, чем сериализованные данные JSON.
Другие методы сериализации
- XML
- JSON
- Jackson
- FastJson
- Hessian
- thrift
- protobuf
- ...
Позже я напишу статью, чтобы поговорить о других методах сериализации и сравнить их производительность и основные принципы использования.