FULL PRODUCT VERSION :
I found different java versions that are affected:
java version "1.7.0_11"
Java(TM) SE Runtime Environment (build 1.7.0_11-b21)
Java HotSpot(TM) 64-Bit Server VM (build 23.6-b04, mixed mode)
java version "1.7.0_25"
Java(TM) SE Runtime Environment (build 1.7.0_25-b15)
Java HotSpot(TM) 64-Bit Server VM (build 23.25-b01, mixed mode)
java version "1.7.0_40"
OpenJDK Runtime Environment (IcedTea 2.4.1) (suse-8.18.1-x86_64)
OpenJDK 64-Bit Server VM (build 24.0-b50, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Linux xxx.xxx.xxx 3.7.10-1.16-default #1 SMP Fri May 31 20:21:23 UTC 2013 (97c14ba) x86_64 x86_64 x86_64 GNU/Linux
openSuSE 12.3
A DESCRIPTION OF THE PROBLEM :
- System time is 10:00:00 UTC.
- Start Thread.sleep(TimeUnit.MINUTES.toMillis(5))
- Change system time to 9:50:00 UTC
=> Thread.sleep(TimeUnit.MINUTES.toMillis(5)) returns at 10:05:00 UTC and not on 9:55:00 UTC.
The problem does not exist with older kernels.
I have tested
Linux xxx 2.6.31.14-0.8-default #1 SMP 2011-04-06 18:09:24 +0200 x86_64 x86_64 x86_64 GNU/Linux
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Run the attached test case, e.g. java SleepTest 1. It prints out the current system time once a second
2. Modify the system time backwards, e.g.
# date
Thu Aug 29 11:00:00 UTC 2013
# date +%T -s "10:50:00"
# date
Thu Aug 29 10:50:01 UTC 2013
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The output of the SleepTest program should continue printing out the new system time (10:50:xx) once a second after the system time has been modified.
Expected output:
10:59:57
10:59:58
10:59:59
11:00:00
10:50:00
10:50:01
...
ACTUAL -
The SleepTest program stops until the system time has reached the old time before the time change. It continues not until system time has reached 11:00:01 again.
Actual output:
10:59:57
10:59:58
10:59:59
11:00:00
11:00:01
11:00:02
(program does not output anything for 10 minutes between 11:00:00 and 11:00:01)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.TimeZone;
public class SleepTest
{
private TimeZone defaultTimeZone = null;
private final String TIME_FORMAT = " HH:mm:ss ";
private SimpleDateFormat timeFormat = null;
SleepTest(int seconds)
{
this.defaultTimeZone = TimeZone.getDefault();
this.timeFormat = new SimpleDateFormat(this.TIME_FORMAT);
this.timeFormat.setTimeZone(this.defaultTimeZone);
System.out.println("interval: " + seconds + " seconds");
System.out.println(Calendar.getInstance(this.defaultTimeZone).getTime());
for (;;)
{
try
{
Thread.sleep(seconds * 1000);
System.out.println(Calendar.getInstance(this.defaultTimeZone).getTime());
}
catch (Exception e)
{
System.out.println(Calendar.getInstance(this.defaultTimeZone).getTime());
System.out.println(e);
}
}
}
public static void main(String[] args)
{
int seconds = 1;
if (args.length > 0)
{
seconds = Integer.valueOf(args[0]);
}
new SleepTest(seconds);
try
{
Thread.sleep(1000000000);
}
catch (Exception e)
{
}
}
}
---------- END SOURCE ----------