Как я могу десериализовать объект, если он был перемещен в другой пакет или переименован?

Рассмотрите следующую ситуацию:

Существует файл сериализации, созданный более старой версией приложения. К сожалению, пакет изменился для класса, который был сериализирован. И теперь я должен загрузить информацию из этого файла в тот же класс, но расположенный в другом пакете. Этот класс имеет serialVersionUID определенный и не изменился (т.е. совместимо).

Вопрос: действительно ли возможно загрузить новые экземпляры класса из этого файла с помощью каких-либо приемов (кроме тривиального копирования класса в старый пакет и затем использование логики обертки десериализации)? Возможно использовать readResolve() восстановиться с перемещения/переименования класса? В противном случае объясните почему.

34
задан Community 23 May 2017 в 12:02
поделиться

3 ответа

Вопрос: Можно ли загрузить экземпляры нового класса из этого файла с помощью каких-либо уловок (кроме тривиальных {{ 1}} копируя класс в старый пакет и затем используя логику десериализации оболочки )?

Я не думаю, что есть какие-то другие "уловки", которые не включают хотя бы частичную повторную реализацию протокола сериализации.

Можно ли использовать readResolve () для восстановления после перемещения / переименования класса ? Если нет, объясните почему.

Нет, потому что механизм десериализации выйдет из строя намного раньше, на этапе, когда он пытается найти класс, который десериализуется - у него нет возможности узнать, что класс в другом пакете имеет readResolve () , который предполагается использовать.

5
ответ дан 27 November 2019 в 16:33
поделиться

Я не думаю, что возможно делать то, что вы хотите.

Формат файла сериализации сохраняет имена классов. Подробно он имеет следующую структуру:

AC ED

номер версии протокола

данные объекта

описание класса объекта

Описание класса имеет следующий формат:

полное имя класса

серийная версия уникальна ID (SHA1 из подписей полей и методов)

параметры сериализации

дескрипторы полей

Когда вы пытаетесь десериализовать объект, механизм сериализации сначала сравнивает имена классов (и вы не проходите этот шаг), затем он сравнивает serialVersionUID и только после прохождения этих двух шагов десериализует объект.

2
ответ дан 27 November 2019 в 16:33
поделиться

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

Если у вас много таких сериализованных объектов, возможно, вы можете написать небольшой сценарий для этого, чтобы "изменение схемы" происходило за один раз.

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

5
ответ дан 27 November 2019 в 16:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: