【发布时间】:2014-12-28 17:41:27
【问题描述】:
我们有一个 32 位客户端进程,它通过 CORBA 与运行在远程机器上的旧服务器应用程序进行通信。这已经运行了大约 12 年,运行良好且可靠。
我们需要(暂时)将我们的客户端进程切换到 64 位以获得更多内存(等待即将进行的重写),并且几乎立即遇到了 remote 应用程序的一些问题。该过程反复崩溃。最初这是没有意义的,如果远程应用程序使用诸如 CORBA 之类的平台无关协议,它怎么能对客户端应用程序 VM 敏感?
经过几天的调查,我们发现远程进程崩溃与客户端 VM 无关,但似乎与我们发送的参数的顺序有关。
我们将请求的结果类型数组发送到服务器,这最初是从 config 中取出并放入 HashSet 中,在最后一分钟转换为数组。服务器应用程序似乎对请求的结果类型的顺序很敏感。
例如如果我们发送 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 时,我们会遇到类似的问题吗?
【问题讨论】:
-
我认为这几乎是不可能的。如果您的应用程序的其他区域依赖于相同或相似的行为,而这些行为只是偶然的(!),那么您甚至可能会被 Java 的不同版本之间的类似问题所困扰。
-
我不能代表 Java,但我可以告诉你,在 C# 中,当 MSFT 实现 64 位版本时,对此类问题的影响为零。原因是 32 位和 64 位应用程序的主要区别在于可寻址性,而不是功能。硬件层的寄存器有更多的空间,它们不再是 4 个字节,而是 8 个字节。但是为了适应遗留应用程序。有一些独特的事情必须发生,例如有两个注册表、两个程序文件路径等。但是 IDE 完美地处理了它。对开发者来说大部分是透明的。
-
hashCode 不依赖于 32 位/64 位,它总是相同的,HashSet 的行为也是如此。如果您从旧版本的 Java 切换到支持 64 位的更新版本,则可能会发生变化。注意:您可以通过在 64 位操作系统而不是 32 位操作系统上运行 32 位 JVM 来获得更多内存。这将最大限度地减少更改次数。
-
我们从 1.6u45 32 位切换到 u45 64 位。相同的版本,我们肯定看到了我没想到的差异。我们迫切希望摆脱 Java 6,但我们需要先从旧版本的 RHEL 更新我们所有的主机。
标签: java java-8 32bit-64bit