java.io.InvalidClassException:本地类不兼容:
我创建了客户端和服务器,然后在客户端添加了一个类用于序列化,然后只是转到我硬盘中客户端的文件夹并将其粘贴到服务器相应位置,分别是classname.class
和classname.java
。 。
它在我自己的笔记本电脑上运行良好但是当我想继续我在其他系统上的工作时,当我打开项目文件夹并在客户端尝试连接到服务器后,出现以下错误:
Exception in thread "main" java.io.InvalidClassException: projectname.clasname; local class incompatible: stream classdesc serialVersionUID = -6009442170907349114, local class serialVersionUID = 6529685098267757690 at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:562) at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1582) at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1495) at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1731) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
到底是怎么回事? 是因为我使用较旧版本的IDE运行程序?
编辑
import java.io.Serializable; import java.net.URL; public class KeyAdr implements Serializable { private static final long serialVersionUID = 6529685098267757690L; public URL adr; public String key; }
如果一个类没有在代码中明确定义private static final long serialVersionUID
,它将被自动生成,并且不能保证不同的机器将生成相同的id; 看起来这正是发生的事情。 此外,如果类以任何方式不同(使用不同版本的类),则自动生成的serialVersionUID
也将不同。
从Serializable
接口的文档 :
如果可序列化类未显式声明
serialVersionUID
,则序列化运行时将基于类的各个方面计算该类的默认serialVersionUID
值,如Java(TM)对象序列化规范中所述。 但是, 强烈建议所有可序列化类显式声明serialVersionUID
值,因为默认的serialVersionUID
计算对类详细信息高度敏感,这些详细信息可能因编译器实现而异,因此在反序列化期间可能会导致意外的InvalidClassExceptions
。 因此,为了保证跨不同java编译器实现的一致serialVersionUID
值,可序列化类必须声明显式serialVersionUID
值。 强烈建议显式serialVersionUID
声明尽可能使用private
修饰符,因为此类声明仅适用于立即声明的类 –serialVersionUID
字段作为inheritance成员无用。 数组类不能声明显式的serialVersionUID
,因此它们始终具有默认的计算值,但是对于数组类,不需要匹配serialVersionUID
值。
您应该在类定义中定义serialVersionUID
,例如:
class MyClass implements Serializable { private static final long serialVersionUID = 6529685098267757690L; ...
有一件事可能发生:
- 1:使用给定的库A(版本X)创建序列化数据
- 2:然后尝试使用相同的库A(但是版本Y)读取此数据
因此,在版本X的编译时,JVM将生成第一个序列ID(对于版本X),并且它将对另一个版本Y(另一个序列ID)执行相同的操作。
当您的程序尝试反序列化数据时,它不能,因为这两个类没有相同的序列ID,并且您的程序无法保证两个Serialized对象对应于相同的类格式。
假设您在平均时间内更改了构造函数,这对您来说应该是有意义的。
我相信这是因为您在客户端和服务器上使用同一类的不同版本。 它可以是不同的数据字段或方法
exception消息清楚地表明,类版本(包括类元数据)也随着时间的推移而发生变化。 换句话说,序列化期间的类结构在反序列化期间是不同的。 这很可能是“继续”。
java中的序列化并不意味着长期持久性或传输格式 – 它太脆弱了。 由于类字节码和JVM存在最微小的差别,因此您的数据不再可读。 为您的任务使用XML或JSON数据绑定( XStream快速且易于使用,并且有大量替代方案)