Java - изменение serialVersionUID двоичного сериализованного объекта

Несколько месяцев назад я сериализовал объект java.io.Serializable в файл. Теперь мне нужно прочитать содержимое, но с тех пор serialVersionUID изменился, и теперь я получаю ошибку «несовместимость классов». Я точно знаю, что ни один из элементов данных не изменился, поэтому единственным препятствием является проверка serialVersionUID.

Есть ли способ отключить проверку или изменить serialVersionUID в двоичном файле?

РАЗЪЯСНЕНИЕ

Этот вопрос предполагает, что я не могу редактировать источник. Есть ли способ взломать файл .class или, возможно, взломать сериализованный объектный файл (использовать шестнадцатеричный редактор и изменить значение с определенным смещением)?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
0
5 638
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Документировано, что сериализация не предназначена для использования для сохранения данных. Чтобы вернуть эти данные, вам нужно будет понизить версию вашей JVM до версии, которая использовалась для вывода этих данных.

Для справки в будущем не используйте сериализацию для сохранения данных между сеансами JVM.

Вы может используете сериализацию таким образом, пока вы устанавливаете serialVersionUID. Из документа Serializable - «Следовательно, чтобы гарантировать согласованное значение serialVersionUID в различных реализациях компилятора Java, сериализуемый класс должен объявить явное значение serialVersionUID».

CurtainDog 16.04.2009 17:19

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

mostruash 22.02.2013 17:49

Почему бы не изменить serialVersionUID в текущей версии, как описано в документации Сериализация?

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

Matthew Brubaker 15.01.2009 01:21

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

Matthew Brubaker 15.01.2009 01:22

Неважно, если класс не находится под его контролем. Он может просто написать новый с тем же именем, членами и serialVersionUID.

Adrian Pronk 15.01.2009 01:30

Это будет работать только в том случае, если в классе нет элементов, которые сломаются при десериализации из старой версии. Если вы удалите переменную-член и попытаетесь обмануть ее с помощью serialVersionUID, она вызовет десериализацию исключения из старых файлов.

Steve B. 18.01.2009 05:23

@SteveB: Прочтите вопрос: «Я точно знаю, что ни один из элементов данных не изменился, поэтому единственным препятствием является проверка serialVersionUID».

Jon Skeet 18.01.2009 10:38
Ответ принят как подходящий

В качестве взлома вы можете сгенерировать serialVer, который, вероятно, использует ваш jvm, используя инструмент serialver:

serialver -classpath независимо от com.foo.bar.MyClass

Если вы затем вручную установите serialVerUID в своем классе, он должен совпадать, и вы должны иметь возможность загружаться, при условии, что вы не изменили класс таким образом, чтобы сделать его недействительным.

Чтобы это работало, вам нужен доступ к файлу класса, каким он был при сериализации объекта. Надеюсь, он в архиве контроля версий?

Adrian Pronk 15.01.2009 01:28

Вы также можете написать свой собственный readObject, я думаю, что вы, вероятно, сможете читать поля в объявленном порядке.

Steve B. 15.01.2009 01:31

Недавно я оказался в аналогичной ситуации - у меня были несколько сериализованных объектов, которые мне пришлось прочитать, serialVersionUID этих объектов отличался от последней версии, и в моем случае в файле хранилось несколько разных serialVersionUID для один и тот же класс (очевидно, хранящийся в разное время). Так что у меня не было возможности изменить класс и установить его serialVersionUID; Мне действительно пришлось пойти и изменить сохраненные данные.

Я понял (читая исходный код java.io), что объект сериализуется, сначала сохраняя имя класса (используя writeUTF()), а затем сразу после использования writeLong() для сохранения serialVersionUID.

Мое решение заключалось в том, чтобы перехватить исключение, затем вернуться, найти имя класса и сразу после имени класса заменить старый serialVersionUID новым.

Другие вопросы по теме