java.io.InvalidClassException:

  InvalidClassException:本地类不兼容:stream classdesc serialVersionUID = -196410440475012755,local class serialVersionUID = -6675950253085108747 

我在以下场景中使用InvalidClassException进行结构化。 在这里,我的EAR安装在4个Websphere App服务器中,并在此之间共享执行。 有时我从POJO类得到exceptionInvalidClassException,它实现了Serializable接口。 请对此有任何线索。 我对此没有任何线索。

当您实现java.io.Serializable接口以使类可序列化时,编译器将查找名为“serialVersionUID”的类型为long的静态最终字段。 如果类没有明确声明该字段,那么编译器将创建一个这样的字段并为其分配一个值,该值来自serialVersionUID的依赖于实现的计算。 此计算取决于类的各个方面,并遵循Sun提供的对象序列化规范。 但是,并不保证所有编译器实现的值都相同。

此值用于检查类与序列化的兼容性,这是在对已保存对象进行反序列化时完成的。 Serialization Runtimevalidation发送方类的serialVersionUID(用于保存流上对象的状态)和接收方类(用于恢复对象的类,可能在某些其他系统中)的serialVersionUID两者完全相同。 如果接收器系统加载了具有一些其他serialVersionUID的类,而不是序列化过程中使用的类,那么我们得到一个InvalidClassException。

注意 – 强烈建议您显式声明并初始化long类型的静态最终字段,并在要使其成为Serializable的所有类中命名为“serialVersionUID”,而不是依赖于此字段值的默认计算。 此计算非常敏感,并且可能因编译器实现而异,因此即使对于同一个类,您也可能会因为在序列化过程的发送方和接收方端使用不同的编译器实现而获得InvalidClassException。

在大多数情况下,您将仅对此字段使用“私有”访问说明符,因为声明通常仅适用于声明它的类,我们实际上不需要在子类中inheritance此字段或从外部访问它。 所以,几乎没有任何理由我们不应该保持它“私密”。

当您尝试反序列化使用同一类的不兼容(通常更早)版本序列化的对象时,会出现该exception。

如果未在实现Serializable的类中明确指定serialVersionUID ,则将根据类的(非transient )字段生成值。 这样做是为了确保不会恢复部分对象(最好是失败而不是盲目地继续使用可能已损坏的对象)。

在Web应用程序系统中,序列化的常见用途是用于会话:如果您将值放入会话中,则最终可能会将其序列化(用于群集支持或仅用于获取持久会话)。

因此要么保持所有类在版本之间兼容, 要么确保不恢复它们不会破坏您的应用程序(即不以这种方式存储重要信息)。

如果有人再次讨论EJB TimerTask这个问题 – 就像我刚才所做的那样 – 如果你正在使用WebSphere Application Server,这里有一个提示:

配置文件的bin文件夹中有2个批处理文件/ shell脚本,可以列出和删除EJB计时器任务。 在我的情况下,我有一些计时器任务,使用不同的,过时的serialVersionUID序列化对象。 我无法摆脱它们,因为序列化的对象确实发生了变化。 所以我只是用过那些:

findEJBTimers.bat cancelEJBTimers.bat

您的计时器任务已经消失,错误消息也是如此。 在我的情况下,这正是我所需要的,但很难得到这个信息。

好的,所以我会问一个例子和我的作品:

以下是各种forms的PoJos序列化的列表和性能指标

您将不得不判断性能和便利性的权衡。 但是,因为我说“JSON”作为序列化的一种手段,所以这里是一个简单的例子,它不依赖于编译器。 基本上,除非你在接收端更改pojo的结构,否则在编译它的时间/方式/位置完全无关紧要(事实上,它甚至不必在两个JVM之间)。 正如您从链接中看到的那样,JSON实际上是最慢的,而XML只是一个有效载荷猪。 但是它们都具有普遍支持的决定性优势。 XML甚至允许应用样式表。

   com.google.code.gson gson 2.3.1 test  

  @Test public void testJSON() throws Exception { Foo expected = new Foo(1,"Christian",1000000.00d); Gson gson = new GsonBuilder().setPrettyPrinting().create(); String testJson = gson.toJson(expected); System.out.println(testJson); Foo result = gson.fromJson(testJson, Foo.class); assertEquals(expected,result); } public static class Foo { private String name; private Integer age; private Double paycheck; public Foo(Integer age, String name, Double paycheck) { this.age = age; this.name = name; this.paycheck = paycheck; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Foo foo = (Foo) o; if (age != null ? !age.equals(foo.age) : foo.age != null) return false; if (name != null ? !name.equals(foo.name) : foo.name != null) return false; if (paycheck != null ? !paycheck.equals(foo.paycheck) : foo.paycheck != null) return false; return true; } @Override public int hashCode() { int result = name != null ? name.hashCode() : 0; result = 31 * result + (age != null ? age.hashCode() : 0); result = 31 * result + (paycheck != null ? paycheck.hashCode() : 0); return result; } } 

产量

 { "name": "Christian", "age": 1, "paycheck": 1000000.0 }