2009-08-24 6 views
18

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

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

+0

Что происходит в случае добавления метода в класс? Можно ли прочитать старый сериализованный объект с помощью модифицированного сериализованного класса? – sprezzatura

+0

Методы не представляют собой состояние объекта, поэтому нет проблем с чтением сериализованного объекта, если вы не используете какой-либо serialVersionUID .. –

ответ

12

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

} 

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

0

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

В документе содержится раздел о нем для Serializable.

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

+0

Обратите внимание, что его следует называть serialVersionUID (не: serialversionuid - Java чувствителен к регистру), и это должен быть частным статическим окончательным). – Jesper

+0

Согласен. Но есть ли способ прочитать сгенерированный uid из сериализованных данных? – paweloque

5

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

Я думаю, что эта статья может вам помочь: The Java serialization algorithm revealed.

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

21

Там простой способ выяснить serialversionUID из

классового

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

import java.io.Serializable; 

public class TestSerializable implements Serializable { 

} 

Вобще this-

serialver -classpath . TestSerializable 

Отпечатки -

static final long serialVersionUID = 5832063776451490808L; 

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

+2

Но это работает только в том случае, если у вас есть старая версия класса TestSerializable. Проблема lewap заключается в том, что он не знает, что значение serialVersionUID было со старой версией класса объекта, который он сериализовал. Если он больше не нуждается в старой версии этого класса, он не может использовать serialver для выяснения. – Jesper

+0

это - какой контроль версий для. – james

13

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

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

Надеется, что это поможет вам тоже.

0

есть гораздо более простой способ, чтобы получить serialVersionUID из сериализованном объекта - просто десериализации его с Apache Commons сериализации утилитами в одном классе с различной серийной версии UID и прочитать сообщение об исключении, которое будет более или менее:

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

0

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

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

Смежные вопросы