Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Differences in collections implementations between 32 bit and 64 bit, any pitfalls we need to worry about?

We have a 32 bit client process that communicates via CORBA to a legacy server application running on a remote machine. This has run well and reliably for about 12 years.

We needed to (temporarily) switch our client process to 64 bit to get more memory (pending an imminent rewrite) and almost immediately ran into some problems with the remote application. The process crashed repeatedly. Initially this made no sense, how can a remote application be sensitive to a client application VM if it uses a platform agnostic protocol such as CORBA?

After a couple of days investigation we found that the remote process crashing has nothing to do with the client VM but does appear to be down to the ordering of parameters we send.

We send an array of requested result types to the server, this is originally taken from config and put into a HashSet, converting to an array at the last minute. The server application appears to be sensitive to the order of the requested result types.

E.g. If we send PV (0), DELTA (1), NPV (2), GAMMA (3) it's fine. If we send GAMMA (3), PV (0), DELTA (1), NPV(2) the remote application crashes. This just appears to be a weird bug in the remote application that has never been exposed before because the order has always been numeric (by chance).

It's the switch to 64 bit that appeared to make the difference, the 64 bit version produces a different ordering of elements from the HashSet. This isn't something I expected but I suspect that HashCodes are only deterministic on a platform basis.

Ensuring that the array is sorted before sending has fixed the issue. Switching to a TreeSet would help as well but thats deep in a library somewhere.

Are there any other oddities between 32 bit and 64 bit we need to worry about? So far, I've been impressed as to how easy the conversion was, no other code changes at all.

At the moment we are on Java 6 and the move to Java 8 is imminent. Can we expect similar issues when moving to Java 8?

like image 219
Fortyrunner Avatar asked Mar 19 '23 00:03

Fortyrunner


1 Answers

First of all, Java bytecode is platform-independent. You can run the same bytecode on a 32-bit or 64-bit JVM; you do not need to recompile your code for a specific platform.

Implementations of Map in general do not have a specified iteration order, so you should not write programs that depend on the order of elements in for example a HashMap. If you do that, as you have discovered, then there is a bug in your application. If you need a specific iteration order, use for example LinkedHashMap (which keeps the elements in insertion order) or TreeMap (which keeps the elements sorted, using whatever criteria you specify).

It's possible that if there is more memory available (for example because you use a 64-bit JVM instead of a 32-bit JVM, with different memory settings), HashMap behaves differently. It's also possible that if you use a slightly different JVM version (for example, Java 6 update X instead of Java 6 update Y) the iteration order will be different.

There is no list anywhere that lists the implementation-specific changes. If you write Java programs that depend undocumented implementation details of a specific Java version, then it's ofcourse possible that your program won't work anymore on any other Java version.

Oracle has a Compatibility Guide for JDK 8 which explains in which ways exactly Java 8 has minor incompatibilities with previous versions, but this only covers changes in the Java API, not implementation details.

If you do upgrade from Java 6 to Java 8 (which is recommended anyway, because Java 6 is no longer supported), then test your programs before you put them into production.

like image 161
Jesper Avatar answered Apr 26 '23 16:04

Jesper