Нахождение serialVersionUID сериализованного объекта - PullRequest
19 голосов
/ 24 августа 2009

Есть ли способ определить сгенерированный serialVersionUID сериализованного объекта Java?

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

Ответы [ 9 ]

22 голосов
/ 24 августа 2009

Существует простой способ узнать serialversionUID класса-

Предположим, у вас есть класс, в котором вы забыли упомянуть serialversionUID-

import java.io.Serializable;

public class TestSerializable implements Serializable {

}

Просто сделай это -

serialver -classpath . TestSerializable

Это печатает-

static final long serialVersionUID = 5832063776451490808L;

serialver - это утилита, которая поставляется вместе с JDK

20 голосов
/ 09 ноября 2014

Это работает для меня:

long serialVersionUID = ObjectStreamClass.lookup(YourObject.getClass()).getSerialVersionUID();

Надеюсь, вам это тоже поможет.

12 голосов
/ 24 августа 2009

Вы можете сделать это, расширив 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();
  }

}

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

5 голосов
/ 24 августа 2009

Есть метаданные, связанные с сериализованными битами (заголовок, если хотите). Вы можете прочитать значение из метаданных, если знаете, в каком положении оно находится (там записано SerialVersionUID вместе с другой информацией, такой как имя класса).

Думаю, эта статья может вам помочь: Алгоритм сериализации Java показал .

Обратите внимание, что биты написаны "в чистом виде" (если вы не зашифровали поток явно), поэтому вам может понадобиться редактор HEX, чтобы увидеть, что такое SerialVersionUID.

1 голос
/ 05 декабря 2017

enter image description here для разработчиков Android,

Вы также можете включить проверку сериализации в меню «Настройки» -> «Редактор» -> «Проверки» -> сначала включить «Сериализуемый класс без проверки« serialVersionUID »», затем ALT + ENTER, студия создаст для вас serialVersionUID.

1 голос
/ 24 августа 2009

Существует указанная грамматика для сериализации объектов:

См. Главу 6.4 в http://java.sun.com/javase/6/docs/platform/serialization/spec/serialTOC.html

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

0 голосов
/ 01 сентября 2018

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

0 голосов
/ 04 июля 2016

Существует гораздо более простой способ получить serialVersionUID сериализованного объекта - просто десериализовать его с помощью утилит сериализации apache commons в тот же класс с другой последовательной версией uid и прочитать сообщение об исключении, которое будет более или менее:

org.apache.commons.lang.SerializationException: java.io.InvalidClassException: my.example.SerializableClass; несовместимый локальный класс: поток classdesc serialVersionUID = -1, локальный класс serialVersionUID = -2

0 голосов
/ 24 августа 2009

Это именно то, что вы должны сделать - укажите свой static final long serialVersionUID.

В документации есть раздел для Сериализуемый .

Если вы не указали serialVersionUID Я не верю, что есть простой способ получить его, кроме расшифровки потока, как предлагает @WMR.

...