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

Thread.join(long millis) waits longer than expected if system date is modified

XMLWordPrintable

    • x86_64
    • windows

      FULL PRODUCT VERSION :
      java version "9.0.4"
      Java(TM) SE Runtime Environment (build 9.0.4+11)
      Java HotSpot(TM) 64-Bit Server VM (build 9.0.4+11, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows [Version 10.0.16299.309]

      A DESCRIPTION OF THE PROBLEM :
      The Thread.join(long millis) function uses System.currentTimeMillis() to measure elapsed time. This is a faulty behaviour as it depends on the system time. The function should use System.nanoTime() instead.

      The attached testcase showcases that if the user changes the system date while the main thread is waiting for the first to finish, the join method can take significantly longer time to complete.

      This bug rarely occurs, but it distrupt expected application flow. The bug can occur when daylight savings time is being used.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Run the attached test case, and while the main thread is waiting, set the system date 1 hour backward.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      ThreadJoinDeadlock.main() started
      ThreadJoinDeadlock.main(...).new Thread() {...}.run() thread running
      ThreadJoinDeadlock.main() end join after 10000 ms

      ACTUAL -
      ThreadJoinDeadlock.main() started
      ThreadJoinDeadlock.main(...).new Thread() {...}.run() thread running
      ThreadJoinDeadlock.main(...).new Thread() {...}.run() thread exit
      ThreadJoinDeadlock.main() end join after 60001 ms


      REPRODUCIBILITY :
      This bug can be reproduced rarely.

      ---------- BEGIN SOURCE ----------
      package test;

      public class ThreadJoinDeadlock {
      public static void main(String[] args) {
      Thread t = new Thread() {
      @Override
      public void run() {
      System.out.println("ThreadJoinDeadlock.main(...).new Thread() {...}.run() thread running");
      try {
      Thread.sleep(60 * 1000);
      } catch (InterruptedException e) {
      e.printStackTrace();
      }
      System.out.println("ThreadJoinDeadlock.main(...).new Thread() {...}.run() thread exit");
      }
      };
      t.setDaemon(true);
      long joinstart = System.nanoTime();
      System.out.println("ThreadJoinDeadlock.main() started");
      t.start();
      try {
      t.join(10 * 1000);
      } catch (InterruptedException e) {
      }
      long joinend = System.nanoTime();
      System.out.println("ThreadJoinDeadlock.main() end join after " + (joinend - joinstart) / 1_000_000 + " ms");
      }
      }

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

            robm Robert Mckenna
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: