Java序列化1.4与1.6的区别

4

我有一个Java程序需要编译为1.4版本,另一个程序可以是任何版本(1.4或1.6),两个程序需要相互传递序列化对象。如果我在两个程序都能访问的地方定义一个可序列化类,Java的序列化是否仍然有效,还是只能使用1.6-1.6或1.4-1.4?


我是唯一一个在跨语言/跨平台/可能随时间变化的类之间使用序列化机制时从不信任它的人吗? 如果性能不是关键,我倾向于将其序列化为XML并返回... - Uri
@Uni,通常情况下,我只会在进程之间使用序列化,如果这两个进程从完全相同的jar包中获取序列化类,比如当这两个进程在同一台机器上。如果这些进程在不同的机器上,我会选择使用XML。 - Paul Tomblin
5个回答

5

确保要序列化的类定义并分配一个值给static final long serialVersionUID,你就可以了。

话虽如此,通常我不会这样做。我的偏好是仅在单个进程内或在两个进程之间使用普通序列化,并且这些进程位于同一台机器上并从同一JAR文件中获取序列化类。如果不是这种情况,序列化为XML是更好、更安全的选择。


3
除了serialVersionUID,包结构在序列化时也必须保持一致。因此,如果你在1.4中有myjar.mypackage.myclass,那么在1.6中也必须是myjar.mypackage.myclass
在包结构中添加Java版本或发布版本并不罕见。即使在编译之间serialVersionUID保持不变,包结构也会导致不兼容版本异常在运行时被抛出。
顺便说一下,如果你在类中实现了Serializable,并且缺少serialVersionUID,你应该会收到编译器警告。
在我看来(基于多年的苦涩经验),Java本地序列化存在很多问题,如果可能的话应该避免使用,特别是因为有出色的XML/JSON支持。如果你确实需要本地序列化,我建议你将类隐藏在接口后面,并在后台实现工厂模式,在需要时创建一个正确类的对象。
你也可以使用这个抽象来检测不兼容的版本异常,并在幕后执行必要的转换以迁移对象中的数据。

1

Java库类在1.4和1.6之间的序列化形式应该是兼容的,除非另有说明。Swing明确声明它在版本之间不兼容,因此如果您尝试序列化Swing对象,则会遇到问题。

您可能会遇到由javac生成的代码略有不同的问题。这将更改serialVersionUID。您应该确保在所有可序列化的类中显式声明UID。


如果您没有显式声明serialVersionUID,那么当使用完全相同的代码、编译器和环境进行两次不同的编译时,可能会出现关于不同版本的异常。 - Paul Tomblin
@Paul:我认为默认的 serialVersionUID 已经很好地作为类成员函数进行了说明。我从未见过它会出现不明原因的更改。你能描述一个发生这种情况的场景吗? - erickson
是的,如果编译器在用于计算 serialVersionUID 的数据中添加随机性,那将是一个奇怪的编译器(尽管从技术上讲符合规范,我相信)。 - Tom Hawtin - tackline
我也没想到会有所不同,但请阅读此处第4.6节的说明http://java.sun.com/j2se/1.5.0/docs/guide/serialization/spec/class.html#4100 - Robin
计算对可能因编译器实现而有所不同的类细节非常敏感,但如果这些细节保持恒定,则变化 UID 的编译器可能是奇怪的(但不一定是不兼容的)。 - Tom Hawtin - tackline
我同意汤姆的看法。实际上,我曾经见过JVM无法创建正确的serialversionUID,但这是一个供应商承认的错误(在特定版本的JRockit中)。 顺便说一下,计算serialVersionUID的不是编译器;对于我刚刚谈到的错误,我运行了Sun和JRockit的“serialver”,并得到了不同的结果。 - Nicolas C

1

不,JVM的不同版本不会破坏序列化本身。

如果您要序列化的某些对象来自Java运行时,并且它们的类发生了不兼容的演变,那么您将会看到失败。大多数核心Java类都非常小心谨慎,但过去某些包中存在不连续性。

我已经成功地使用序列化(在RMI的上下文中)多年,其中包括来自不同编译和不同版本的Java运行时的类。

我不想偏离原始问题太远,但我想指出,无论格式如何,演变序列化类总是需要注意。这不是Java序列化特有的问题。无论您是在XML、JSON、ASN.1等中进行序列化,都必须处理相同的概念。Java序列化提供了一个相当清晰的规范,说明了允许的内容以及如何进行允许的更改。有时这是限制性的,有时有处方是很有帮助的。


0

如果双方使用相同的jar文件,大多数情况下它会正常工作。但是,如果您使用不同版本的同一软件包/模块/框架(例如不同的weblogic jars或某些“罕见”异常的扩展用法),则需要进行大量的集成测试,然后才能获得批准。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接