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

nano time does not increment while the system is asleep

XMLWordPrintable

    • generic
    • os_x

      A DESCRIPTION OF THE PROBLEM :
      When calculating the elapsed time, the duration drifts between System.currentTimeMillis() and System.nanoTime() when the system is put to sleep. The millisecond time source for continues to accrue whereas the nano time source is paused. This does not appear to comply with a simple reading of the JavaDoc for what one might expect would be included within the the elapsed time.

      "This method can only be used to measure elapsed time and is not related to any other notion of system or wall-clock time."

      This issue was discovered in [1] where the user did not appear have submitted this here as recommended. An expirable cache used nanoTime() to determine the remaining duration to not be impacted the wall clock was modified (e.g. by ntpd). This resulted in the application using a stale authentication token due to the excessive drift.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1. Read the current milli and nano time sources
      2. Put the machine to sleep
      3. Wake the machine up
      4. Read the current time sources and compare the durations

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      0: Delta by millis=1 vs nanos=1
      1: Delta by millis=2 vs nanos=2
      2: Delta by millis=3 vs nanos=3
      3: Delta by millis=4 vs nanos=4
      ...
      99: Delta by millis=100 vs nanos=100
      100: Delta by millis=101 vs nanos=101
      101: Delta by millis=102 vs nanos=102

      ACTUAL -
      0: Delta by millis=1 vs nanos=1
      1: Delta by millis=2 vs nanos=2
      2: Delta by millis=3 vs nanos=3
      3: Delta by millis=4 vs nanos=4
      ...
      34: Delta by millis=35 vs nanos=35
      ... // sleep
      35: Delta by millis=96 vs nanos=36
      36: Delta by millis=97 vs nanos=37
      37: Delta by millis=98 vs nanos=38


      ---------- BEGIN SOURCE ----------
      import java.time.Duration;
      import java.util.concurrent.TimeUnit;

      import org.testng.annotations.Test;



      public class NanoTimeTest {

        @Test
        public void test() throws InterruptedException {
          long startMillis = System.currentTimeMillis();
          long startNanos = System.nanoTime();

          for (int i = 1; ; i++) {
            TimeUnit.SECONDS.sleep(1);
            System.out.printf("%d: Delta by millis=%s vs nanos=%s%n", i,
                Duration.ofMillis(System.currentTimeMillis() - startMillis).toSeconds(),
                Duration.ofNanos(System.nanoTime() - startNanos).toSeconds());
          }
        }
      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Use System.currentTimeMillis() for elapsed time measurements.

      FREQUENCY : always


            dholmes David Holmes
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

              Created:
              Updated:
              Resolved: