【问题标题】:Getting InvalidClassException while using newer serialVersionUID使用较新的 serialVersionUID 时出现 InvalidClassException
【发布时间】:2015-08-12 20:47:42
【问题描述】:

我有一个 InvalidClassException 类,序列号为 private static final long serialVersionUID = -5086279873877116405L;。此类的 serialVersionUID 的旧值为 -6871353730928221293L。

现在我遇到了异常

java.io.InvalidClassException: com.navtech.kernel.flat.FlatValidationException; local class incompatible: stream classdesc serialVersionUID = -6871353730928221293, local class serialVersionUID = -5086279873877116405L.

这里有什么问题。

【问题讨论】:

  • 这是与序列化有关的问题。请检查此SO post
  • 没有得到ClassCastException,或者FlatValidationException,不管是什么。阅读它。
  • FlatValidationException 是我的班级名称

标签: java classcastexception


【解决方案1】:

这是意料之中的。 serialVersionUID 用于区分同一 Serializable 类的不同版本。版本变化很可能是有充分理由的,确实不能反序列化为新版本。

【讨论】:

  • 发生了代码更改,我们删除了一些属性,这就是我们更改 serialVersionUID 的原因。那么解决这个问题的解决方案是什么。从哪里获取旧的 serialVersionUID。
  • 如果是这种情况,您将无法再反序列化这些对象。如果您需要了解其中的内容,可以使用jdeserialize 等工具。
【解决方案2】:

当一个对象被序列化时,serialVersionUID 与其他内容一起被序列化。

稍后在反序列化时,从反序列化对象中提取 serialVersionUID 并与加载的类的 serialVersionUID 进行比较。

数字不匹配所以这个例外。

要解决此问题:- 在反序列化之前使用新的 serialVersionUID 序列化类。

【讨论】:

    【解决方案3】:

    文档中指定的不兼容更改:

    对类的不兼容更改是那些无法保证互操作性的更改。进化类时可能发生的不兼容变化是:

    • 删除字段 - 如果在类中删除字段,写入的流将不包含其值。当流被较早的类读取时,该字段的值将设置为默认值,因为流中没有可用的值。但是,此默认值可能会对早期版本履行其合同的能力产生不利影响。

    • 在层次结构中向上或向下移动类 - 这是不允许的,因为流中的数据以错误的顺序出现。

    • 将非静态字段更改为静态或将非瞬态字段更改为 瞬态 在依赖默认序列化时,这种变化相当于从类中删除一个字段。 此版本的类不会将该数据写入流,因此该类的早期版本将无法读取该数据。与删除字段时一样,早期版本的字段将被初始化为默认值,这可能会导致类以意想不到的方式失败。

    • 更改原始字段的声明类型 该类的每个版本都使用其声明的类型写入数据。尝试读取该字段的早期版本的类将失败,因为流中的数据类型与该字段的类型不匹配。

    • 更改 writeObject 或 readObject

      方法,使其不再写入或读取默认字段数据或更改它,以便在以前的版本没有写入或读取时尝试写入或读取。默认字段数据必须一致地出现或不出现在流中。

    • 将类从 Serializable 更改为 Externalizable,反之亦然

      是不兼容的更改,因为流将包含与可用类的实现不兼容的数据。

    • 将类从非枚举类型更改为枚举类型,反之亦然

      因为流将包含与可用类的实现不兼容的数据。

    • 删除 Serializable 或 Externalizable 是不兼容的 改变

      自从编写后,它将不再提供旧版本类所需的字段。

    • 添加 writeReplace 或 readResolve 方法

      如果行为会产生与任何旧版本的类不兼容的对象,则该类是不兼容的。

    在您的情况下,移动类层次结构可能会出现问题,因为当存在继承问题时,具有自己特定 serialUID 的类将不会在已生成的流中被覆盖。 强烈建议所有可序列化的类都显式声明 serialVersionUID 值,因为默认的 serialVersionUID 计算对类细节高度敏感,这些细节可能因编译器实现而异,因此可能在反序列化期间导致意外的 InvalidClassExceptions。 希望这会有所帮助!

    【讨论】:

      猜你喜欢
      • 2012-11-15
      • 2015-02-07
      • 2013-03-19
      • 1970-01-01
      • 2019-10-05
      • 2013-12-18
      • 2012-12-25
      • 2019-09-02
      • 1970-01-01
      相关资源
      最近更新 更多