21

有没有办法确定生成serialVersionUID的序列化 Java 对象?

问题是我序列化了一个对象而没有明确指定serialVersionUID. 现在反序列化过程抱怨类不兼容。但是,我没有以使其不兼容的方式更改课程。所以我假设serialVersionUID在类中指定它就足够了,因为它存储在对象数据中。为了做到这一点,我需要serialVersionUID从序列化数据中读取。

4

9 回答 9

28

这对我有用:

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

希望对你也有帮助。

于 2014-11-08T22:15:18.077 回答
25

有一种简单的方法可以找出类的 serialversionUID -

假设您有一个课程,您忘记提及 serialversionUID-

import java.io.Serializable;

public class TestSerializable implements Serializable {

}

就这样做——

serialver -classpath . TestSerializable

这打印-

static final long serialVersionUID = 5832063776451490808L;

serialver 是 JDK 附带的实用程序

于 2009-08-24T13:14:35.767 回答
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();
  }

}

我相信可以通过替换方法返回的描述符来读取所有的序列化数据,但我没有尝试过。

于 2009-08-24T12:46:58.103 回答
5

有与序列化位相关的元数据(如果您愿意,可以使用标头)。如果您知道它在哪个位置,则可以从元数据中读取值(SerialVersionUID与其他信息一起写在那里,例如类名)。

我认为这篇文章可能会对您有所帮助:Java 序列化算法揭示

请注意,这些位是“清楚地”写入的(除非您明确加密了流),因此您可能只需要一个 HEX 编辑器来查看SerialVersionUID.

于 2009-08-24T13:06:39.217 回答
1

对象的序列化有一个指定的语法:

请参阅http://java.sun.com/javase/6/docs/platform/serialization/spec/serialTOC.html中的第 6.4 章

使用它,您应该能够确定序列化对象的 SerialVersionUID。

于 2009-08-24T12:26:56.363 回答
1

在此处输入图像描述 对于安卓开发者,

您也可以先从 Settings -> Editor -> Inspections -> 启用“Serializable class without 'serialVersionUID' check”启用序列化检查,然后按 ALT+ ENTER,工作室将为您创建 serialVersionUID。

于 2017-12-05T03:30:24.853 回答
0

这正是你应该做的——指定你自己的static final long serialVersionUID.

Serializable的文档中有一个关于它的部分。

除非您指定了,否则serialVersionUID我认为除了按照@WMR 建议的那样解密流之外,没有其他简单的方法可以获取它。

于 2009-08-24T12:24:30.530 回答
0

有更简单的方法来获取序列化对象的 serialVersionUID - 只需使用 apache commons serialization utils 将其反序列化到具有不同序列版本 uid 的同一类并读取或多或少的异常消息:

org.apache.commons.lang.SerializationException:java.io.InvalidClassException:my.example.SerializableClass;本地类不兼容:流 classdesc serialVersionUID = -1,本地类 serialVersionUID = -2

于 2016-07-04T10:41:49.020 回答
0

获得它的最简单方法(尤其是在难以找到的情况下)是为 serialVersionUID 定义任何数字并在反序列化失败时监视堆栈跟踪,它将打印出原始的。

于 2018-09-01T07:06:06.183 回答