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