Apparant bug in the JVM
Stephen Colebourne
scolebourne at joda.org
Mon Nov 11 05:23:29 PST 2013
I was sent this piece of test code by Dirk Lemmermann. It fails
randomly on JDK8 b114
import static java.time.temporal.ChronoUnit.DAYS;
import java.time.Instant;
public class TestInstantBug {
public static void main(String[] args) {
Instant now = Instant.now();
System.out.println("now = " + now);
for (int i = 0; i < 100000; i++) {
System.out.println(i);
Instant truncated = now.truncatedTo(DAYS);
System.out.println(truncated);
}
}
}
The code does not change any variables during the loop. Instant is
immutable and well written to my knowledge.
My debugging shows some horrible behaviour.
I copied Instant.java and edited it, adding it to the bootclasspath.
This is the original code in Instant.java:
private static Instant create(long seconds, int nanoOfSecond) {
if ((seconds | nanoOfSecond) == 0) {
return EPOCH;
}
if (seconds < MIN_SECOND || seconds > MAX_SECOND) {
throw new DateTimeException("Instant exceeds minimum or
maximum instant");
}
return new Instant(seconds, nanoOfSecond);
}
The second if statement randomly fails.
Worse, the use of a System.out.println() on the "seconds" variable
causes the if statement to reset.
Given this test code:
private static Instant create(long seconds, int nanoOfSecond) {
if ((seconds | nanoOfSecond) == 0) {
return EPOCH;
}
System.out.println(seconds < MIN_SECOND || seconds > MAX_SECOND);
if (seconds < MIN_SECOND || seconds > MAX_SECOND) {
System.out.println(MIN_SECOND);
System.out.println(MAX_SECOND);
System.out.println(seconds);
System.out.println(seconds < MIN_SECOND);
System.out.println(seconds > MAX_SECOND);
System.out.println(seconds < MIN_SECOND || seconds > MAX_SECOND);
System.out.println("Create " + seconds);
System.out.println(MIN_SECOND);
System.out.println(MAX_SECOND);
System.out.println(seconds);
System.out.println(seconds < MIN_SECOND);
System.out.println(seconds > MAX_SECOND);
System.out.println(seconds < MIN_SECOND || seconds > MAX_SECOND);
throw new DateTimeException("Instant exceeds minimum or
maximum instant");
}
return new Instant(seconds, nanoOfSecond);
}
the output is (when it actually fails):
true // the if statement randomly returned true
-31557014167219200
31556889864403199
1384128000
false // the two parts of the if statement return false
false // the two parts of the if statement return false
true // the if statement still returns true
Create 1384128000 // system out resets it
-31557014167219200
31556889864403199
1384128000
false
false
false // the if statement returns false
Exception in thread "main" java.time.DateTimeException: Instant
exceeds minimum or maximum instant
at java.time.Instant.create(Instant.java:422)
at java.time.Instant.ofEpochSecond(Instant.java:327)
at java.time.Instant.plus(Instant.java:940)
at java.time.Instant.plusNanos(Instant.java:918)
at java.time.Instant.truncatedTo(Instant.java:773)
at TestInstantBug.main(TestInstantBug.java:13)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Hope you can squash this bug. b114 needs a big warning sign on it.
Stephen
More information about the hotspot-dev
mailing list