FULL PRODUCT VERSION :
$ java -version
java version "1.5.0_06"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_06-b05)
Java HotSpot(TM) Server VM (build 1.5.0_06-b05, mixed mode)
On Solaris 10 we used 1.5.0_05-b05.
It also failed on a 6.0 release we tried.
FULL OS VERSION :
$ uname -a
Linux localhost.localdomain 2.4.21-4.ELsmp #1 SMP Fri Oct 3 17:52:56 EDT 2003 i686 i686 i386 GNU/Linux
EXTRA RELEVANT SYSTEM CONFIGURATION :
Also fails on all other platforms we tried:
- Solaris 10
- Windows XP
A DESCRIPTION OF THE PROBLEM :
The original problem encountered was that the following expression, when Y is Integer.MAX_VALUE and list.size() is four, was evaluating to true when X is zero but to false when X is one:
((X <= Y) && (X < list.size()))
Of course, this should be true for all values of X between zero and three when Y is Integer.MAX_VALUE. (Perhaps a Hotspot optimization based on the fact that (X <= Integer.MAX_VALUE) is always true is misbehaving.)
Although it was clearly failing in my application I was unable to reproduce the particular case above in a standalone test, but I was able to produce a (hopefully) related problem. After a number of iterations, giving Hotspot time to compile the code, the following expression is always evaluated to true:
((X <= Y) && (X < 10))
Where:
X varies between 0 and Integer.MAX_VALUE
Y is Integer.MAX_VALUE
The expression should be only true when X is less than 10. This is the case when -client is used, but after compilation with -server the expression is always true. The included test demonstrates this problem.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the test included with the java -server option. It will fail. Run it with -client and it won't fail.
EXPECTED VERSUS ACTUAL BEHAVIOR :
Expected result:
No failure
Actual result:
Exception in thread "main" java.lang.RuntimeException: Failed test iteration=9029 max=2147483647 counted=2147483647 expected=10
at MaxValueBug.doTest(MaxValueBug.java:27)
at MaxValueBug.main(MaxValueBug.java:14)
ERROR MESSAGES/STACK TRACES THAT OCCUR :
$ javac MaxValueBug.java && java -server -cp . MaxValueBug
Exception in thread "main" java.lang.RuntimeException: Failed test iteration=9029 max=2147483647 counted=2147483647 expected=10
at MaxValueBug.doTest(MaxValueBug.java:27)
at MaxValueBug.main(MaxValueBug.java:14)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
public class MaxValueBug {
static final int N_TESTS = 1000000000;
public static void main(String[] args) throws Exception {
/*
* If MAX_VALUE is changed to MAX_VALUE - 1 below, the test passes
* because (apparently) bad code is only generated when comparing
* <= MAX_VALUE in the doTest method.
*/
MaxValueBug test = new MaxValueBug();
for (int i = 0; i < N_TESTS; i += 1) {
test.doTest(10, Integer.MAX_VALUE, i);
//test.doTest(10, Integer.MAX_VALUE - 1, i);
}
System.out.println("No failure");
}
void doTest(int expected, int max, int i) {
int counted;
for (counted = 0;
(counted <= max) && (counted < expected);
counted += 1) {
}
if (counted != expected) {
throw new RuntimeException("Failed test iteration=" + i +
" max=" + max +
" counted=" + counted +
" expected=" + expected);
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
The workaround, for the specific case we encountered, is to not use Integer.MAX_VALUE as a maximum value but rather (Integer.MAX_VALUE - 1). This happens to be acceptable for this one case. We are, of course, very concerned about this bug in other contexts.