Поиск serialVersionUID сериализованного объекта
Есть ли способ определить сгенерированный serialVersionUID
сериализованного объекта Java?
Проблема заключается в том, что я сериализую объект без явного указания serialVersionUID
. Теперь процесс десериализации жалуется на несовместимость классов. Однако я не изменил класс таким образом, чтобы сделать его несовместимым. Поэтому я предполагаю, что достаточно указать serialVersionUID
в классе, поскольку он хранится в данных объекта. Для этого мне нужно прочитать serialVersionUID
из сериализованных данных.
Ответы
Ответ 1
Вы можете сделать это, расширив ObjectInputStream:
public class PrintUIDs extends ObjectInputStream {
public PrintUIDs(InputStream in) throws IOException {
super(in);
}
@Override
protected ObjectStreamClass readClassDescriptor() throws IOException,
ClassNotFoundException {
ObjectStreamClass descriptor = super.readClassDescriptor();
System.out.println("name=" + descriptor.getName());
System.out.println("serialVersionUID=" + descriptor.getSerialVersionUID());
return descriptor;
}
public static void main(String[] args) throws IOException,
ClassNotFoundException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
List<Object> list = Arrays.asList((Object) new Date(), UUID.randomUUID());
oos.writeObject(list);
oos.close();
InputStream in = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new PrintUIDs(in);
ois.readObject();
}
}
Я считаю, что можно было бы прочитать все сериализованные данные, заменив дескриптор, возвращаемый методом, но я его не пробовал.
Ответ 2
Там есть простой способ узнать serialversionUID класса -
Предположим, у вас есть класс, в котором вы забыли упомянуть serialversionUID -
import java.io.Serializable;
public class TestSerializable implements Serializable {
}
Просто сделайте это -
serialver -classpath . TestSerializable
Это означает, что
static final long serialVersionUID = 5832063776451490808L;
serialver - это утилита, которая поставляется вместе с JDK
Ответ 3
Это работает для меня:
long serialVersionUID = ObjectStreamClass.lookup(YourObject.getClass()).getSerialVersionUID();
Надеюсь, что это тоже поможет.
Ответ 4
Есть метаданные, связанные с сериализованными битами (заголовок, если хотите). Вы можете прочитать значение из метаданных, если знаете, в какой позиции оно (там написано SerialVersionUID
, а также другая информация, такая как имя класса).
Я думаю, эта статья может вам помочь: Алгоритм сериализации Java показал.
Обратите внимание, что биты записываются "в ясности" (если вы явно не зашифровали поток), поэтому вам может понадобиться редактор HEX, чтобы узнать, что такое SerialVersionUID
.
Ответ 5
Существует определенная грамматика для сериализации объектов:
См. главу 6.4 в
http://java.sun.com/javase/6/docs/platform/serialization/spec/serialTOC.html
Используя это, вы сможете определить SerialVersionUID вашего сериализованного объекта.
Ответ 6
Что именно вы должны делать - укажите свой static final long serialVersionUID
.
Здесь есть раздел об этом в документах для Serializable.
Если вы не указали serialVersionUID
, я не верю, что есть простой способ сделать это иначе, чем расшифровать поток, как предлагает @WMR.
Ответ 7
существует гораздо более простой способ получить serialVersionUID сериализованного объекта - просто десериализуйте его с помощью apache commons serialization utils в том же классе с разной версией uid и прочтите сообщение об исключении, которое будет более или менее:
org.apache.commons.lang.SerializationException: java.io.InvalidClassException: my.example.SerializableClass; локальный класс несовместим: stream classdesc serialVersionUID = -1, локальный класс serialVersionUID = -2
Ответ 8
для разработчиков Android,
вы также можете включить проверку сериализации из "Настройки" → "Редактор" → "Инспекции" → включить "Сериализуемый класс без" serialVersionUID ", а затем ALT + ENTER, студия создаст для вас serialVersionUID.