8068730: Increase the precision of the implementation of java.time.Clock.systemUTC()

Changes the implementation of java.time.Clock.systemUTC() to take advantage of the maximum resolution of the underlying native clock on which System.currentTimeMillis() is based.

Reviewed-by: dholmes, rriggs, scolebourne, sla
This commit is contained in:
Daniel Fuchs 2015-01-28 17:52:48 +01:00
parent f6d01b3697
commit 967c448681
17 changed files with 122 additions and 17 deletions

View file

@ -300,6 +300,48 @@ JVM_LEAF(jlong, JVM_NanoTime(JNIEnv *env, jclass ignored))
return os::javaTimeNanos();
JVM_END
// The function below is actually exposed by sun.misc.VM and not
// java.lang.System, but we choose to keep it here so that it stays next
// to JVM_CurrentTimeMillis and JVM_NanoTime
const jlong MAX_DIFF_SECS = 0x0100000000; // 2^32
const jlong MIN_DIFF_SECS = -MAX_DIFF_SECS; // -2^32
JVM_LEAF(jlong, JVM_GetNanoTimeAdjustment(JNIEnv *env, jclass ignored, jlong offset_secs))
JVMWrapper("JVM_GetNanoTimeAdjustment");
jlong seconds;
jlong nanos;
os::javaTimeSystemUTC(seconds, nanos);
// We're going to verify that the result can fit in a long.
// For that we need the difference in seconds between 'seconds'
// and 'offset_secs' to be such that:
// |seconds - offset_secs| < (2^63/10^9)
// We're going to approximate 10^9 ~< 2^30 (1000^3 ~< 1024^3)
// which makes |seconds - offset_secs| < 2^33
// and we will prefer +/- 2^32 as the maximum acceptable diff
// as 2^32 has a more natural feel than 2^33...
//
// So if |seconds - offset_secs| >= 2^32 - we return a special
// sentinel value (-1) which the caller should take as an
// exception value indicating that the offset given to us is
// too far from range of the current time - leading to too big
// a nano adjustment. The caller is expected to recover by
// computing a more accurate offset and calling this method
// again. (For the record 2^32 secs is ~136 years, so that
// should rarely happen)
//
jlong diff = seconds - offset_secs;
if (diff >= MAX_DIFF_SECS || diff <= MIN_DIFF_SECS) {
return -1; // sentinel value: the offset is too far off the target
}
// return the adjustment. If you compute a time by adding
// this number of nanoseconds along with the number of seconds
// in the offset you should get the current UTC time.
return (diff * (jlong)1000000000) + nanos;
JVM_END
JVM_ENTRY(void, JVM_ArrayCopy(JNIEnv *env, jclass ignored, jobject src, jint src_pos,
jobject dst, jint dst_pos, jint length))