JDK-4500388 : Calling Thread.sleep with small argument affects system clock on windows
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version:
    1.3.0,1.3.1,1.3.1_04,1.4.0,1.4.1,5.0u4 1.3.0,1.3.1,1.3.1_04,1.4.0,1.4.1,5.0u4
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: windows_nt,windows_2000,windows_xp
  • CPU: x86
  • Submitted: 2001-09-06
  • Updated: 2012-10-08
  • Resolved: 2002-04-04
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other Other Other
1.3.1_04 04Fixed 1.4.0_02Fixed 1.4.1Fixed
Related Reports
Duplicate :  
Duplicate :  
Relates :  
Relates :  
Relates :  
Relates :  
Description
Multithreading timers less than 10 ms causes Windows clock to run too fast.Compile the test case on JDK 1.3.0 and run on Windows 2000 Professional,Use an independent timer (like a kitchen timer) to measure the execution time of the program.

The 5 ms sleep causes a call to NTSetTimerResolution in the OS to set the timer to 1 ms resolution (in order to discriminate the passage of 5 ms).
 The multithreading of the timers is causing a problem.
 
 The problem is not observed in classic mode, or using the MS virtual machine.

 TESTCASEBEGIN
 /**
  * This class is meant to demonstrate an issue with the system time when 
running the HotSpot VM and sleeping for less than 10 ms. When it is run with the HotSpot VM, the system time will be off. The program will run for 10 system minutes, but when verifying with a stop watch, is took only 9 minutes and 50 seconds.
  * Steps to try this:
  * 1. Set a count-down timer to 10 minutes.
  * 2. At the same moment, run the application and start the count-down timer.
  * 3. At the moment the software stops, stop the timer. When the timer is 
       zero,it means that the system took 10 real minutes. When there is time           left on the timer, the system took less than 10 minutes.
+  * Another way to try this:
+  * 1. Remove the code where the "timer" is created so the application
+  *    will not stop after 10 minutes.
+  * 2. Set an external clock at exactly the same time as the computer clock.
+  * 3. Run the application.
+  * 4. After a couple of hours, compare the system clock with the external 
        clock.
+ Note that the system clock is a couple of minutes fast.
   */


 public class TestBase {
    public int launchThread(final int id, final int sleepTime) {
 
       // Create a new thread object
       Thread t = new Thread(new Runnable() {
                                public void run() {
                                   // Loop forever
                                   while (true) {
                                      // Print the ID
                                      System.out.print(""+id);
                                      // Do some processing
                                      for (int i=0; i<1000; i++) {
                                         for (int j=0; j<1000; j++) {
                            double x = (double)i * j / j + i - j * j;
                                        }
                                      }
               // Sleep for the amount specified in the sleep time
                                     
   try {
	Thread.currentThread().sleep(sleepTime);
                 }
                    catch (InterruptedException e) {
                                         ;
                                      }
                                   }
                                }
                             });
       // Start the thread
       t.start();
       return 0;
    }
 
    public static void main(String[] args) {
       // Create a Thread that will print the ms time every 30 seconds
       Thread timer = new Thread(new Runnable() {
                                    public void run() {
                                       // Print the begin time
                                       long start = System.currentTimeMillis();
                      System.out.println("Start time: " + start);
                                       try {
                                          // Sleep for 10 minutes
                                          Thread.currentThread().sleep(600000);
                                       }
                                       catch (InterruptedException e) {
                                          ;
                                       }
                                       // Print the current time
                  System.out.println("time: " +(System.currentTimeMillis() - start));
                                       System.exit(0);
                                    }
                                 });
       // Start the timer thread
       // Remove this line of code when it is not desired to stop the app after 10 minutes.
       timer.start();
 
       // Create a new test base object
       TestBase tb = new TestBase();
 
       // Launch a thread with a 5 ms sleep time
       tb.launchThread(1, 5);
 
       // Launch a thread with a 10 ms sleep time
       tb.launchThread(2, 10);
    }
 }
 
 
 
 
 
 TESTCASEEND

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: 1.3.1_04 1.4.0_02 hopper FIXED IN: 1.3.1_04 1.4.0_02 hopper INTEGRATED IN: 1.3.1_04 1.4.0_02 hopper
14-06-2004

WORK AROUND None
11-06-2004

EVALUATION Hotspot uses Windows routines timeBeginPeriod() and timeEndPeriod() to change the Windows timing resolution from its default value to one millisecond and back during a Thread.sleep(). Frequently changing the resolution appears to be causing errors in Windows time keeping (speculation). Simply avoiding timeBeginPeriod use would cause errors in timing short delays less than 10ms. Here's similar analysis and a suggested solution from Ken Russell: "I don't recommend removing the timeBeginPeriod()/timeEndPeriod() calls because that will prevent sleeps from under 10 ms from working properly. If this is a critical customer issue then one solution would be to provide a product-mode flag which would disable the effect of the HighResolutionInterval class and also set the time interval to 1 ms when the VM starts up, incurring a performance penalty but maintaining correctness. I assume the skew is caused by the multiple calls to timeBeginPeriod()/timeEndPeriod() and not simply by the increasing of the resolution of the timer." (from 8/18/2001 email). ###@###.### 2001-09-18 I ran the test case on an NT 4.0/SP4 system and it ran in 10 minutes two seconds. On a W98/SE system it ran in 10 minutes one second. ###@###.### 2001-09-18
18-09-2001