32位和64位之间的集合实现的差异,我们需要担心的任何陷阱?

时间:2014-11-01 15:53:42

标签: java java-8 32bit-64bit

我们有一个32位客户端进程,它通过CORBA与远程计算机上运行的旧服务器应用程序进行通信。这已经运行良好且可靠了大约12年。

我们需要(暂时)将我们的客户端进程切换到64位以获得更多内存(等待即将重写)并且几乎立即遇到了远程应用程序的一些问题。这个过程反复崩溃。最初这没有任何意义,如果远程应用程序使用与CORBA等平台无关的协议,它如何对客户端应用程序VM敏感?

经过几天的调查后,我们发现远程进程崩溃与客户端虚拟机无关,但似乎与我们发送的参数排序有关。

我们向服务器发送一组请求的结果类型,这最初取自config并放入HashSet,最后一分钟转换为数组。服务器应用程序似乎对请求的结果类型的顺序敏感。

E.g。如果我们发送PV(0),DELTA(1),NPV(2),GAMMA(3)就可以了。如果我们发送GAMMA(3),PV(0),DELTA(1),NPV(2),远程应用程序崩溃。这似乎是远程应用程序中一个奇怪的错误,之前从未暴露过,因为订单始终是数字(偶然)。

切换到64位似乎有所不同,64位版本产生了与HashSet不同的元素排序。这不是我预期的,但我怀疑HashCodes只是在平台上确定性的。

确保在发送之前对数组进行排序已修复问题。切换到TreeSet也会有所帮助,但是在某个库的深处。

32位和64位之间还有其他奇怪的问题我们需要担心吗?到目前为止,我对转换的简单程度印象深刻,其他代码根本没有变化。

目前我们正在使用Java 6,现在迫切需要迁移到Java 8。迁移到Java 8时,我们可以期待类似的问题吗?

1 个答案:

答案 0 :(得分:7)

首先,Java字节码与平台无关。您可以在32位或64位JVM上运行相同的字节码;您无需为特定平台重新编译代码。

Map的实现通常没有指定的迭代顺序,因此您不应编写依赖于元素顺序的程序,例如HashMap。如果您这样做,正如您所发现的那样,那么您的应用程序中就存在一个错误。如果您需要特定的迭代顺序,请使用例如LinkedHashMap(保持元素按插入顺序排列)或TreeMap(使用您指定的任何条件保持元素排序)。

如果有更多可用内存(例如,因为您使用的是64位JVM而不是32位JVM,具有不同的内存设置),HashMap的行为可能会有所不同。如果您使用稍微不同的JVM版本(例如,Java 6更新X而不是Java 6更新Y),迭代顺序也会不同。

在任何地方都没有列出特定于实现的更改的列表。如果您编写的Java程序依赖于特定Java版本的未记录的实现细节,那么您的程序可能不再适用于任何其他Java版本。

Oracle有一个Compatibility Guide for JDK 8,它解释了Java 8与先前版本存在轻微不兼容的方式,但这仅包括Java API中的更改,而不是实现细节。

如果你确实从Java 6升级到Java 8(无论如何都推荐使用,因为不再支持Java 6),那么在将它们投入生产之前测试你的程序。