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

Java 32位和64位之间的集合实现差异,我们需要担心哪些陷阱?,java,java-8,32bit-64bit,Java,Java 8,32bit 64bit,我们有一个32位的客户端进程,它通过CORBA与运行在远程机器上的遗留服务器应用程序进行通信。这项技术在大约12年的时间里运行良好且可靠 我们需要(暂时)将客户端进程切换到64位以获得更多内存(等待即将到来的重写),并且几乎立即在远程应用程序中遇到了一些问题。这个过程一再失败。起初,这毫无意义,如果远程应用程序使用CORBA之类的平台无关协议,它怎么可能对客户端应用程序VM敏感呢 经过几天的调查,我们发现远程进程崩溃与客户端VM无关,但似乎与我们发送的参数顺序有关 我们向服务器发送一个请求结果类

我们有一个32位的客户端进程,它通过CORBA与运行在远程机器上的遗留服务器应用程序进行通信。这项技术在大约12年的时间里运行良好且可靠

我们需要(暂时)将客户端进程切换到64位以获得更多内存(等待即将到来的重写),并且几乎立即在远程应用程序中遇到了一些问题。这个过程一再失败。起初,这毫无意义,如果远程应用程序使用CORBA之类的平台无关协议,它怎么可能对客户端应用程序VM敏感呢

经过几天的调查,我们发现远程进程崩溃与客户端VM无关,但似乎与我们发送的参数顺序有关

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

例如,如果我们发送PV(0)、DELTA(1)、NPV(2)、GAMMA(3)就可以了。如果我们发送GAMMA(3)、PV(0)、DELTA(1)、NPV(2),远程应用程序就会崩溃。这似乎是远程应用程序中一个奇怪的bug,以前从未公开过,因为顺序一直是数字的(碰巧)

切换到64位似乎起到了作用,64位版本产生了不同于哈希集的元素顺序。这不是我所期望的,但我怀疑哈希代码只是在平台基础上确定的

确保在发送之前对数组进行排序已修复该问题。切换到树集也会有帮助,但这在某个图书馆的深处

在32位和64位之间是否还有其他我们需要担心的奇怪之处?到目前为止,我对转换是多么容易印象深刻,没有任何其他代码更改


目前,我们正在使用Java6,即将迁移到Java8。当我们迁移到Java8时,会出现类似的问题吗

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

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

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

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

Oracle有一个解释Java8在哪些方面与以前的版本有轻微的不兼容,但这只包括JavaAPI中的更改,而不包括实现细节


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

我认为这几乎是不可能的。如果您的应用程序的其他部分依赖于相同或类似的行为,而这些行为只是偶然的(!),那么您甚至可能会被Java的不同版本之间的类似问题所困扰。我不能为Java说话,但我可以告诉您,在C#中,当MSFT实现64位版本时,这类问题没有任何影响。原因是32位和64位应用程序的主要区别在于可寻址性,而不是功能。硬件层的寄存器空间更大,不再是4字节,而是8字节。但为了适应遗留应用程序。有一些独特的事情必须发生,例如有两个注册表,两个程序文件路径等,但IDE处理得很好。对开发人员来说基本上是透明的。hashCode不依赖于32位/64位,它将始终保持不变,HashSet的行为也一样。可能的变化是,如果您从旧版本的Java切换到支持64位的更新版本。注意:只需在64位操作系统上运行32位JVM而不是32位操作系统,就可以获得更多内存。这将减少更改的数量。我们将从1.6u45 32位切换到u45 64位。同样的版本,我们确实看到了我没有预料到的差异。我们迫切希望摆脱Java6,但我们需要首先从RHEL的旧版本更新所有HOS。字节码独立性非常棒。我们反序列化了一些使用非常旧的Java版本创建的旧文件,它工作得非常好。如上所述,我们正在升级到8,需要首先升级RHEL。这是最难的部分。