Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8041919

java.time.Clock is wildly inaccurate

XMLWordPrintable

    • Icon: Enhancement Enhancement
    • Resolution: Not an Issue
    • Icon: P4 P4
    • None
    • 8
    • core-libs
    • x86
    • windows_8

      FULL PRODUCT VERSION :
      java version "1.8.0"
      Java(TM) SE Runtime Environment (build 1.8.0-b132)
      Java HotSpot(TM) 64-Bit Server VM (build 25.0-b70, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      Windows Version 6.3.9600 (Windows 8.1, but also 8)

      A DESCRIPTION OF THE PROBLEM :
       1. On Windows, GetSystemTimeAsFileTime returns time with a resolution of 100s of nanoseconds; therefore System.currentTimeMillis() cannot be the best system clock. Documentation says Clock.systemDefaultZone() uses best available clock.
      2. Clock.systemDefaultZone() is supposed to convert time and date values in the time zone of the system on which it is invoked. Instead, clock.instant().now(clock).toString() displays time in UTC.
      3. Where c1 = Clock.systemDefaultZone(), c1.instant().now(c1).toString() and c1.instant().atZone(zoneId).toString() return values with two different millisecond values -- an impossibility.
      4. Clock values instantiated before and after a sleep of 1000 ms report a duration of 5 ms; measured duration was 1,001 ms.

      ADDITIONAL REGRESSION INFORMATION:
      This is not a regression; it is a new feature.

      java version "1.8.0"
      Java(TM) SE Runtime Environment (build 1.8.0-b132)
      Java HotSpot(TM) 64-Bit Server VM (build 25.0-b70, mixed mode)

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Run the following program:
       private static final void testAccuracy(){
              Clock c1 = Clock.systemDefaultZone();
              long before = System.currentTimeMillis();
               try{
                  Thread.sleep(1000); // Sleep for one second
              }catch(InterruptedException ie){
                  ie.printStackTrace();
              }
              Clock c2 = Clock.systemDefaultZone();
              long after = System.currentTimeMillis();
              System.out.println("Clock1: " + c1.instant().now(c1).toString());
              System.out.println("Clock1: " + c1.instant().atZone(zoneId).toString());
              System.out.println("Clock2: " + c2.instant().atZone(zoneId).toString());
              System.out.printf("Clock1: %,12.9f seconds %,d nanos%n", c1.millis()/1000.0, c1.instant().getNano());
              System.out.printf("Clock2: %,12.9f seconds %,d nanos%n", c2.millis()/1000.0, c2.instant().getNano());
              System.out.printf("Before: %,d; After: %,d; difference: %,d%n", before, after, (after - before));
          }

       public static void main(String[] args) {
              testAccuracy();
          }

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Please refer to line #s in Actual Result below.
      Line 1 should be in EDT, not UTC.
      There should be no millisecond difference between lines 1 & 2.
      There should be a time difference of approx. 1 second between lines 2 & 3.
      The millisecond values of lines 1, 2, and 4 should match.
      The millisecond values of lines 3 & 5 should match.
      Lines 4 and 5 should have precision in 100s of nanoseconds, if Java uses best system clock available, as advertised.
      ACTUAL -
      line# Output
      1 Clock1: 2014-04-19T12:19:41.229Z
      2 Clock1: 2014-04-19T08:19:41.305-04:00[America/New_York]
      3 Clock2: 2014-04-19T08:19:41.308-04:00[America/New_York]
      4 Clock1: 1,397,909,981.308000000 seconds 308,000,000 nanos
      5 Clock2: 1,397,909,981.313000000 seconds 313,000,000 nanos
      6 Before: 1,397,909,980,228; After: 1,397,909,981,229; difference: 1,001

      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      Clock1: 2014-04-19T12:19:41.229Z
      Clock1: 2014-04-19T08:19:41.305-04:00[America/New_York]
      Clock2: 2014-04-19T08:19:41.308-04:00[America/New_York]
      Clock1: 1,397,909,981.308000000 seconds 308,000,000 nanos
      Clock2: 1,397,909,981.313000000 seconds 313,000,000 nanos
      Before: 1,397,909,980,228; After: 1,397,909,981,229; difference: 1,001

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      private static final void testAccuracy(){
              Clock c1 = Clock.systemDefaultZone();
              long before = System.currentTimeMillis();
               try{
                  Thread.sleep(1000); // Sleep for one second
              }catch(InterruptedException ie){
                  ie.printStackTrace();
              }
              Clock c2 = Clock.systemDefaultZone();
              long after = System.currentTimeMillis();
              System.out.println("Clock1: " + c1.instant().now(c1).toString());
              System.out.println("Clock1: " + c1.instant().atZone(zoneId).toString());
              System.out.println("Clock2: " + c2.instant().atZone(zoneId).toString());
              System.out.printf("Clock1: %,12.9f seconds %,d nanos%n", c1.millis()/1000.0, c1.instant().getNano());
              System.out.printf("Clock2: %,12.9f seconds %,d nanos%n", c2.millis()/1000.0, c2.instant().getNano());
              System.out.printf("Before: %,d; After: %,d; difference: %,d%n", before, after, (after - before));
          }

         public static void main(String[] args) {
              testAccuracy();
          }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      There is no simple workaround. If one wants to access the best available system clock on Windows, one must use JNI. It is not possible to use the new java.time API until these problems are fixed.

            rriggs Roger Riggs
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: