Несколько месяцев назад я сериализовал объект java.io.Serializable в файл. Теперь мне нужно прочитать содержимое, но с тех пор serialVersionUID изменился, и теперь я получаю ошибку «несовместимость классов». Я точно знаю, что ни один из элементов данных не изменился, поэтому единственным препятствием является проверка serialVersionUID.
Есть ли способ отключить проверку или изменить serialVersionUID в двоичном файле?
РАЗЪЯСНЕНИЕ
Этот вопрос предполагает, что я не могу редактировать источник. Есть ли способ взломать файл .class или, возможно, взломать сериализованный объектный файл (использовать шестнадцатеричный редактор и изменить значение с определенным смещением)?




Документировано, что сериализация не предназначена для использования для сохранения данных. Чтобы вернуть эти данные, вам нужно будет понизить версию вашей JVM до версии, которая использовалась для вывода этих данных.
Для справки в будущем не используйте сериализацию для сохранения данных между сеансами JVM.
Это может быть правдой, учитывая, что вы не можете получить доступ к своим данным и вернуть их, если обновите свой класс. Что вам нужно сделать, так это загрузить данные с помощью необновленной версии вашего класса, передать их новому классу и снова сериализовать (во время выполнения), что в большинстве ситуаций нецелесообразно.
Почему бы не изменить serialVersionUID в текущей версии, как описано в документации Сериализация?
То, как был написан его вопрос, указывает на то, что объект не находится под его контролем, чтобы иметь возможность внести это изменение.
Но если это так, то да. Изменение serialVersionUID обратно на то, что было, когда он записывал данные, позволит ему прочитать их обратно.
Неважно, если класс не находится под его контролем. Он может просто написать новый с тем же именем, членами и serialVersionUID.
Это будет работать только в том случае, если в классе нет элементов, которые сломаются при десериализации из старой версии. Если вы удалите переменную-член и попытаетесь обмануть ее с помощью serialVersionUID, она вызовет десериализацию исключения из старых файлов.
@SteveB: Прочтите вопрос: «Я точно знаю, что ни один из элементов данных не изменился, поэтому единственным препятствием является проверка serialVersionUID».
В качестве взлома вы можете сгенерировать serialVer, который, вероятно, использует ваш jvm, используя инструмент serialver:
serialver -classpath независимо от com.foo.bar.MyClass
Если вы затем вручную установите serialVerUID в своем классе, он должен совпадать, и вы должны иметь возможность загружаться, при условии, что вы не изменили класс таким образом, чтобы сделать его недействительным.
Чтобы это работало, вам нужен доступ к файлу класса, каким он был при сериализации объекта. Надеюсь, он в архиве контроля версий?
Вы также можете написать свой собственный readObject, я думаю, что вы, вероятно, сможете читать поля в объявленном порядке.
Недавно я оказался в аналогичной ситуации - у меня были несколько сериализованных объектов, которые мне пришлось прочитать, serialVersionUID этих объектов отличался от последней версии, и в моем случае в файле хранилось несколько разных serialVersionUID для один и тот же класс (очевидно, хранящийся в разное время). Так что у меня не было возможности изменить класс и установить его serialVersionUID; Мне действительно пришлось пойти и изменить сохраненные данные.
Я понял (читая исходный код java.io), что объект сериализуется, сначала сохраняя имя класса (используя writeUTF()), а затем сразу после использования writeLong() для сохранения serialVersionUID.
Мое решение заключалось в том, чтобы перехватить исключение, затем вернуться, найти имя класса и сразу после имени класса заменить старый serialVersionUID новым.
Вы может используете сериализацию таким образом, пока вы устанавливаете serialVersionUID. Из документа Serializable - «Следовательно, чтобы гарантировать согласованное значение serialVersionUID в различных реализациях компилятора Java, сериализуемый класс должен объявить явное значение serialVersionUID».