changeset 57801:a59de3ccecab

8235741: Inappropriate uses of os::javaTimeMillis() Reviewed-by: rehn, kbarrett, egahlin, shade
author dholmes
date Fri, 17 Jan 2020 00:52:10 -0500
parents 3b9aed3b1bec
children bc5f701cf740
files src/hotspot/os/aix/os_perf_aix.cpp src/hotspot/os/bsd/semaphore_bsd.cpp src/hotspot/os/linux/os_perf_linux.cpp src/hotspot/os/posix/os_posix.cpp src/hotspot/os/windows/os_perf_windows.cpp src/hotspot/share/compiler/compilationPolicy.cpp src/hotspot/share/compiler/tieredThresholdPolicy.cpp src/hotspot/share/gc/shenandoah/shenandoahHeapRegionCounters.cpp src/hotspot/share/jfr/recorder/repository/jfrChunk.cpp src/hotspot/share/jvmci/jvmciCompiler.cpp src/hotspot/share/logging/logDecorations.cpp src/hotspot/share/logging/logDecorations.hpp src/hotspot/share/runtime/biasedLocking.cpp src/hotspot/share/runtime/safepoint.cpp src/hotspot/share/runtime/safepoint.hpp src/hotspot/share/runtime/threadStatisticalInfo.hpp src/hotspot/share/runtime/vmOperations.hpp src/hotspot/share/runtime/vmThread.cpp src/hotspot/share/services/gcNotifier.cpp src/hotspot/share/services/heapDumper.cpp src/hotspot/share/utilities/globalDefinitions.hpp src/hotspot/share/utilities/ostream.cpp
diffstat 22 files changed, 136 insertions(+), 104 deletions(-) [+]
line wrap: on
line diff
--- a/src/hotspot/os/aix/os_perf_aix.cpp	Wed Jan 22 12:35:24 2020 -0800
+++ b/src/hotspot/os/aix/os_perf_aix.cpp	Fri Jan 17 00:52:10 2020 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -371,19 +371,21 @@
 
 static int perf_context_switch_rate(double* rate) {
   static pthread_mutex_t contextSwitchLock = PTHREAD_MUTEX_INITIALIZER;
-  static uint64_t      lastTime;
+  static uint64_t      bootTime;
+  static uint64_t      lastTimeNanos;
   static uint64_t      lastSwitches;
   static double        lastRate;
 
-  uint64_t lt = 0;
+  uint64_t bt = 0;
   int res = 0;
 
-  if (lastTime == 0) {
+  // First time through bootTime will be zero.
+  if (bootTime == 0) {
     uint64_t tmp;
     if (get_boot_time(&tmp) < 0) {
       return OS_ERR;
     }
-    lt = tmp * 1000;
+    bt = tmp * 1000;
   }
 
   res = OS_OK;
@@ -394,20 +396,29 @@
     uint64_t sw;
     s8 t, d;
 
-    if (lastTime == 0) {
-      lastTime = lt;
+    if (bootTime == 0) {
+      // First interval is measured from boot time which is
+      // seconds since the epoch. Thereafter we measure the
+      // elapsed time using javaTimeNanos as it is monotonic-
+      // non-decreasing.
+      lastTimeNanos = os::javaTimeNanos();
+      t = os::javaTimeMillis();
+      d = t - bt;
+      // keep bootTime zero for now to use as a first-time-through flag
+    } else {
+      t = os::javaTimeNanos();
+      d = nanos_to_millis(t - lastTimeNanos);
     }
 
-    t = os::javaTimeMillis();
-    d = t - lastTime;
-
     if (d == 0) {
       *rate = lastRate;
-    } else if (!get_noof_context_switches(&sw)) {
+    } else if (get_noof_context_switches(&sw) == 0) {
       *rate      = ( (double)(sw - lastSwitches) / d ) * 1000;
       lastRate     = *rate;
       lastSwitches = sw;
-      lastTime     = t;
+      if (bootTime != 0) {
+        lastTimeNanos = t;
+      }
     } else {
       *rate = 0;
       res   = OS_ERR;
@@ -416,6 +427,10 @@
       *rate = 0;
       lastRate = 0;
     }
+
+    if (bootTime == 0) {
+      bootTime = bt;
+    }
   }
   pthread_mutex_unlock(&contextSwitchLock);
 
--- a/src/hotspot/os/bsd/semaphore_bsd.cpp	Wed Jan 22 12:35:24 2020 -0800
+++ b/src/hotspot/os/bsd/semaphore_bsd.cpp	Fri Jan 17 00:52:10 2020 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -76,17 +76,17 @@
   // kernel semaphores take a relative timeout
   mach_timespec_t waitspec;
   int secs = millis / MILLIUNITS;
-  int nsecs = (millis % MILLIUNITS) * NANOSECS_PER_MILLISEC;
+  int nsecs = millis_to_nanos(millis % MILLIUNITS);
   waitspec.tv_sec = secs;
   waitspec.tv_nsec = nsecs;
 
-  int64_t starttime = os::javaTimeMillis() * NANOSECS_PER_MILLISEC;
+  int64_t starttime = os::javaTimeNanos();
 
   kr = semaphore_timedwait(_semaphore, waitspec);
   while (kr == KERN_ABORTED) {
     // reduce the timout and try again
-    int64_t totalwait = millis * NANOSECS_PER_MILLISEC;
-    int64_t current = os::javaTimeMillis() * NANOSECS_PER_MILLISEC;
+    int64_t totalwait = millis_to_nanos(millis);
+    int64_t current = os::javaTimeNanos();
     int64_t passedtime = current - starttime;
 
     if (passedtime >= totalwait) {
--- a/src/hotspot/os/linux/os_perf_linux.cpp	Wed Jan 22 12:35:24 2020 -0800
+++ b/src/hotspot/os/linux/os_perf_linux.cpp	Fri Jan 17 00:52:10 2020 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -431,19 +431,21 @@
 
 static int perf_context_switch_rate(double* rate) {
   static pthread_mutex_t contextSwitchLock = PTHREAD_MUTEX_INITIALIZER;
-  static uint64_t      lastTime;
+  static uint64_t      bootTime;
+  static uint64_t      lastTimeNanos;
   static uint64_t      lastSwitches;
   static double        lastRate;
 
-  uint64_t lt = 0;
+  uint64_t bt = 0;
   int res = 0;
 
-  if (lastTime == 0) {
+  // First time through bootTime will be zero.
+  if (bootTime == 0) {
     uint64_t tmp;
     if (get_boot_time(&tmp) < 0) {
       return OS_ERR;
     }
-    lt = tmp * 1000;
+    bt = tmp * 1000;
   }
 
   res = OS_OK;
@@ -454,20 +456,29 @@
     uint64_t sw;
     s8 t, d;
 
-    if (lastTime == 0) {
-      lastTime = lt;
+    if (bootTime == 0) {
+      // First interval is measured from boot time which is
+      // seconds since the epoch. Thereafter we measure the
+      // elapsed time using javaTimeNanos as it is monotonic-
+      // non-decreasing.
+      lastTimeNanos = os::javaTimeNanos();
+      t = os::javaTimeMillis();
+      d = t - bt;
+      // keep bootTime zero for now to use as a first-time-through flag
+    } else {
+      t = os::javaTimeNanos();
+      d = nanos_to_millis(t - lastTimeNanos);
     }
 
-    t = os::javaTimeMillis();
-    d = t - lastTime;
-
     if (d == 0) {
       *rate = lastRate;
-    } else if (!get_noof_context_switches(&sw)) {
+    } else if (get_noof_context_switches(&sw) == 0) {
       *rate      = ( (double)(sw - lastSwitches) / d ) * 1000;
       lastRate     = *rate;
       lastSwitches = sw;
-      lastTime     = t;
+      if (bootTime != 0) {
+        lastTimeNanos = t;
+      }
     } else {
       *rate = 0;
       res   = OS_ERR;
@@ -476,6 +487,10 @@
       *rate = 0;
       lastRate = 0;
     }
+
+    if (bootTime == 0) {
+      bootTime = bt;
+    }
   }
   pthread_mutex_unlock(&contextSwitchLock);
 
--- a/src/hotspot/os/posix/os_posix.cpp	Wed Jan 22 12:35:24 2020 -0800
+++ b/src/hotspot/os/posix/os_posix.cpp	Fri Jan 17 00:52:10 2020 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -681,7 +681,7 @@
 
 void os::naked_short_sleep(jlong ms) {
   assert(ms < MILLIUNITS, "Un-interruptable sleep, short time use only");
-  os::naked_short_nanosleep(ms * (NANOUNITS / MILLIUNITS));
+  os::naked_short_nanosleep(millis_to_nanos(ms));
   return;
 }
 
@@ -1833,18 +1833,18 @@
     abstime->tv_nsec = 0;
   } else {
     abstime->tv_sec = seconds;
-    abstime->tv_nsec = millis * (NANOUNITS / MILLIUNITS);
+    abstime->tv_nsec = millis_to_nanos(millis);
   }
 }
 
-static jlong millis_to_nanos(jlong millis) {
+static jlong millis_to_nanos_bounded(jlong millis) {
   // We have to watch for overflow when converting millis to nanos,
   // but if millis is that large then we will end up limiting to
   // MAX_SECS anyway, so just do that here.
   if (millis / MILLIUNITS > MAX_SECS) {
     millis = jlong(MAX_SECS) * MILLIUNITS;
   }
-  return millis * (NANOUNITS / MILLIUNITS);
+  return millis_to_nanos(millis);
 }
 
 static void to_abstime(timespec* abstime, jlong timeout,
@@ -1897,7 +1897,7 @@
 // Create an absolute time 'millis' milliseconds in the future, using the
 // real-time (time-of-day) clock. Used by PosixSemaphore.
 void os::Posix::to_RTC_abstime(timespec* abstime, int64_t millis) {
-  to_abstime(abstime, millis_to_nanos(millis),
+  to_abstime(abstime, millis_to_nanos_bounded(millis),
              false /* not absolute */,
              true  /* use real-time clock */);
 }
@@ -1992,7 +1992,7 @@
 
   if (v == 0) { // Do this the hard way by blocking ...
     struct timespec abst;
-    to_abstime(&abst, millis_to_nanos(millis), false, false);
+    to_abstime(&abst, millis_to_nanos_bounded(millis), false, false);
 
     int ret = OS_TIMEOUT;
     int status = pthread_mutex_lock(_mutex);
@@ -2318,7 +2318,7 @@
     if (millis / MILLIUNITS > MAX_SECS) {
       millis = jlong(MAX_SECS) * MILLIUNITS;
     }
-    to_abstime(&abst, millis * (NANOUNITS / MILLIUNITS), false, false);
+    to_abstime(&abst, millis_to_nanos(millis), false, false);
 
     int ret = OS_TIMEOUT;
     int status = pthread_cond_timedwait(cond(), mutex(), &abst);
--- a/src/hotspot/os/windows/os_perf_windows.cpp	Wed Jan 22 12:35:24 2020 -0800
+++ b/src/hotspot/os/windows/os_perf_windows.cpp	Fri Jan 17 00:52:10 2020 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -97,7 +97,7 @@
 */
 typedef struct {
   HQUERY query;
-  s8     lastUpdate; // Last time query was updated (current millis).
+  s8     lastUpdate; // Last time query was updated.
 } UpdateQueryS, *UpdateQueryP;
 
 
@@ -287,8 +287,8 @@
 
 static int collect_query_data(UpdateQueryP update_query) {
   assert(update_query != NULL, "invariant");
-  const s8 now = os::javaTimeMillis();
-  if (now - update_query->lastUpdate > min_update_interval_millis) {
+  const s8 now = os::javaTimeNanos();
+  if (nanos_to_millis(now - update_query->lastUpdate) > min_update_interval_millis) {
     if (PdhDll::PdhCollectQueryData(update_query->query) != ERROR_SUCCESS) {
       return OS_ERR;
     }
--- a/src/hotspot/share/compiler/compilationPolicy.cpp	Wed Jan 22 12:35:24 2020 -0800
+++ b/src/hotspot/share/compiler/compilationPolicy.cpp	Fri Jan 17 00:52:10 2020 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -289,14 +289,14 @@
 public:
   static void decay();
   static bool is_decay_needed() {
-    return (os::javaTimeMillis() - _last_timestamp) > CounterDecayMinIntervalLength;
+    return nanos_to_millis(os::javaTimeNanos() - _last_timestamp) > CounterDecayMinIntervalLength;
   }
 };
 
 jlong CounterDecay::_last_timestamp = 0;
 
 void CounterDecay::decay() {
-  _last_timestamp = os::javaTimeMillis();
+  _last_timestamp = os::javaTimeNanos();
 
   // This operation is going to be performed only at the end of a safepoint
   // and hence GC's will not be going on, all Java mutators are suspended
--- a/src/hotspot/share/compiler/tieredThresholdPolicy.cpp	Wed Jan 22 12:35:24 2020 -0800
+++ b/src/hotspot/share/compiler/tieredThresholdPolicy.cpp	Fri Jan 17 00:52:10 2020 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -304,7 +304,7 @@
 #endif
 
   set_increase_threshold_at_ratio();
-  set_start_time(os::javaTimeMillis());
+  set_start_time(nanos_to_millis(os::javaTimeNanos()));
 }
 
 
@@ -404,7 +404,7 @@
   CompileTask *max_blocking_task = NULL;
   CompileTask *max_task = NULL;
   Method* max_method = NULL;
-  jlong t = os::javaTimeMillis();
+  jlong t = nanos_to_millis(os::javaTimeNanos());
   // Iterate through the queue and find a method with a maximum rate.
   for (CompileTask* task = compile_queue->first(); task != NULL;) {
     CompileTask* next_task = task->next();
@@ -596,7 +596,7 @@
       print_event(COMPILE, mh(), mh(), bci, level);
     }
     int hot_count = (bci == InvocationEntryBci) ? mh->invocation_count() : mh->backedge_count();
-    update_rate(os::javaTimeMillis(), mh());
+    update_rate(nanos_to_millis(os::javaTimeNanos()), mh());
     CompileBroker::compile_method(mh, bci, level, mh, hot_count, CompileTask::Reason_Tiered, thread);
   }
 }
@@ -616,7 +616,7 @@
 
   // We don't update the rate if we've just came out of a safepoint.
   // delta_s is the time since last safepoint in milliseconds.
-  jlong delta_s = t - SafepointTracing::end_of_last_safepoint_epoch_ms();
+  jlong delta_s = t - SafepointTracing::end_of_last_safepoint_ms();
   jlong delta_t = t - (m->prev_time() != 0 ? m->prev_time() : start_time()); // milliseconds since the last measurement
   // How many events were there since the last time?
   int event_count = m->invocation_count() + m->backedge_count();
@@ -641,7 +641,7 @@
 // Check if this method has been stale for a given number of milliseconds.
 // See select_task().
 bool TieredThresholdPolicy::is_stale(jlong t, jlong timeout, Method* m) {
-  jlong delta_s = t - SafepointTracing::end_of_last_safepoint_epoch_ms();
+  jlong delta_s = t - SafepointTracing::end_of_last_safepoint_ms();
   jlong delta_t = t - m->prev_time();
   if (delta_t > timeout && delta_s > timeout) {
     int event_count = m->invocation_count() + m->backedge_count();
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegionCounters.cpp	Wed Jan 22 12:35:24 2020 -0800
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegionCounters.cpp	Fri Jan 17 00:52:10 2020 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2019, Red Hat, Inc. All rights reserved.
+ * Copyright (c) 2016, 2020, Red Hat, Inc. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -75,7 +75,7 @@
 
 void ShenandoahHeapRegionCounters::update() {
   if (ShenandoahRegionSampling) {
-    jlong current = os::javaTimeMillis();
+    jlong current = nanos_to_millis(os::javaTimeNanos());
     jlong last = _last_sample_millis;
     if (current - last > ShenandoahRegionSamplingRate &&
             Atomic::cmpxchg(&_last_sample_millis, last, current) == last) {
--- a/src/hotspot/share/jfr/recorder/repository/jfrChunk.cpp	Wed Jan 22 12:35:24 2020 -0800
+++ b/src/hotspot/share/jfr/recorder/repository/jfrChunk.cpp	Fri Jan 17 00:52:10 2020 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -37,6 +37,8 @@
 // strictly monotone
 static jlong nanos_now() {
   static jlong last = 0;
+  // We use javaTimeMillis so this can be correlated with
+  // external timestamps.
   const jlong now = os::javaTimeMillis() * JfrTimeConverter::NANOS_PER_MILLISEC;
   if (now > last) {
     last = now;
--- a/src/hotspot/share/jvmci/jvmciCompiler.cpp	Wed Jan 22 12:35:24 2020 -0800
+++ b/src/hotspot/share/jvmci/jvmciCompiler.cpp	Fri Jan 17 00:52:10 2020 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -61,7 +61,7 @@
   if (PrintBootstrap) {
     tty->print("Bootstrapping JVMCI");
   }
-  jlong start = os::javaTimeMillis();
+  jlong start = os::javaTimeNanos();
 
   Array<Method*>* objectMethods = SystemDictionary::Object_klass()->methods();
   // Initialize compile queue with a selected set of methods.
@@ -94,7 +94,8 @@
   } while (qsize != 0);
 
   if (PrintBootstrap) {
-    tty->print_cr(" in " JLONG_FORMAT " ms (compiled %d methods)", os::javaTimeMillis() - start, _methods_compiled);
+    tty->print_cr(" in " JLONG_FORMAT " ms (compiled %d methods)",
+                  nanos_to_millis(os::javaTimeNanos() - start), _methods_compiled);
   }
   _bootstrapping = false;
   JVMCI::compiler_runtime()->bootstrap_finished(CHECK);
--- a/src/hotspot/share/logging/logDecorations.cpp	Wed Jan 22 12:35:24 2020 -0800
+++ b/src/hotspot/share/logging/logDecorations.cpp	Fri Jan 17 00:52:10 2020 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,7 +34,7 @@
 const char* volatile LogDecorations::_host_name = NULL;
 
 LogDecorations::LogDecorations(LogLevelType level, const LogTagSet &tagset, const LogDecorators &decorators)
-    : _level(level), _tagset(tagset), _millis(-1) {
+    : _level(level), _tagset(tagset) {
   create_decorations(decorators);
 }
 
@@ -71,13 +71,6 @@
 #undef DECORATOR
 }
 
-jlong LogDecorations::java_millis() {
-  if (_millis < 0) {
-    _millis = os::javaTimeMillis();
-  }
-  return _millis;
-}
-
 #define ASSERT_AND_RETURN(written, pos) \
     assert(written >= 0, "Decorations buffer overflow"); \
     return pos + written;
@@ -100,13 +93,13 @@
 }
 
 char * LogDecorations::create_timemillis_decoration(char* pos) {
-  int written = jio_snprintf(pos, DecorationsBufferSize - (pos - _decorations_buffer), INT64_FORMAT "ms", java_millis());
+  int written = jio_snprintf(pos, DecorationsBufferSize - (pos - _decorations_buffer), INT64_FORMAT "ms", os::javaTimeMillis());
   ASSERT_AND_RETURN(written, pos)
 }
 
 char * LogDecorations::create_uptimemillis_decoration(char* pos) {
   int written = jio_snprintf(pos, DecorationsBufferSize - (pos - _decorations_buffer),
-                             INT64_FORMAT "ms", java_millis() - _vm_start_time_millis);
+                             INT64_FORMAT "ms", nanos_to_millis(os::elapsed_counter()));
   ASSERT_AND_RETURN(written, pos)
 }
 
--- a/src/hotspot/share/logging/logDecorations.hpp	Wed Jan 22 12:35:24 2020 -0800
+++ b/src/hotspot/share/logging/logDecorations.hpp	Fri Jan 17 00:52:10 2020 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -36,12 +36,10 @@
   char* _decoration_offset[LogDecorators::Count];
   LogLevelType _level;
   const LogTagSet& _tagset;
-  jlong _millis;
   static jlong _vm_start_time_millis;
   static const char* volatile _host_name;
 
   const char* host_name();
-  jlong java_millis();
   void create_decorations(const LogDecorators& decorators);
 
 #define DECORATOR(name, abbr) char* create_##name##_decoration(char* pos);
--- a/src/hotspot/share/runtime/biasedLocking.cpp	Wed Jan 22 12:35:24 2020 -0800
+++ b/src/hotspot/share/runtime/biasedLocking.cpp	Fri Jan 17 00:52:10 2020 -0500
@@ -324,7 +324,7 @@
   //    and don't allow rebiasing of these objects. Disable
   //    allocation of objects of that type with the bias bit set.
   Klass* k = o->klass();
-  jlong cur_time = os::javaTimeMillis();
+  jlong cur_time = nanos_to_millis(os::javaTimeNanos());
   jlong last_bulk_revocation_time = k->last_biased_lock_bulk_revocation_time();
   int revocation_count = k->biased_lock_revocation_count();
   if ((revocation_count >= BiasedLockingBulkRebiasThreshold) &&
@@ -374,7 +374,7 @@
                           o->mark().value(),
                           o->klass()->external_name());
 
-  jlong cur_time = os::javaTimeMillis();
+  jlong cur_time = nanos_to_millis(os::javaTimeNanos());
   o->klass()->set_last_biased_lock_bulk_revocation_time(cur_time);
 
   Klass* k_o = o->klass();
--- a/src/hotspot/share/runtime/safepoint.cpp	Wed Jan 22 12:35:24 2020 -0800
+++ b/src/hotspot/share/runtime/safepoint.cpp	Fri Jan 17 00:52:10 2020 -0500
@@ -1142,7 +1142,6 @@
 jlong SafepointTracing::_last_safepoint_sync_time_ns = 0;
 jlong SafepointTracing::_last_safepoint_cleanup_time_ns = 0;
 jlong SafepointTracing::_last_safepoint_end_time_ns = 0;
-jlong SafepointTracing::_last_safepoint_end_time_epoch_ms = 0;
 jlong SafepointTracing::_last_app_time_ns = 0;
 int SafepointTracing::_nof_threads = 0;
 int SafepointTracing::_nof_running = 0;
@@ -1155,8 +1154,6 @@
 void SafepointTracing::init() {
   // Application start
   _last_safepoint_end_time_ns = os::javaTimeNanos();
-  // amount of time since epoch
-  _last_safepoint_end_time_epoch_ms = os::javaTimeMillis();
 }
 
 // Helper method to print the header.
@@ -1256,8 +1253,6 @@
 
 void SafepointTracing::end() {
   _last_safepoint_end_time_ns = os::javaTimeNanos();
-  // amount of time since epoch
-  _last_safepoint_end_time_epoch_ms = os::javaTimeMillis();
 
   if (_max_sync_time < (_last_safepoint_sync_time_ns - _last_safepoint_begin_time_ns)) {
     _max_sync_time = _last_safepoint_sync_time_ns - _last_safepoint_begin_time_ns;
--- a/src/hotspot/share/runtime/safepoint.hpp	Wed Jan 22 12:35:24 2020 -0800
+++ b/src/hotspot/share/runtime/safepoint.hpp	Fri Jan 17 00:52:10 2020 -0500
@@ -252,8 +252,7 @@
   static jlong _last_safepoint_sync_time_ns;
   static jlong _last_safepoint_cleanup_time_ns;
   static jlong _last_safepoint_end_time_ns;
-  // amount of ms since epoch
-  static jlong _last_safepoint_end_time_epoch_ms;
+
   // Relative
   static jlong _last_app_time_ns;
 
@@ -279,11 +278,11 @@
   static void statistics_exit_log();
 
   static jlong time_since_last_safepoint_ms() {
-    return (os::javaTimeNanos() - _last_safepoint_end_time_ns) / (NANOUNITS / MILLIUNITS);
+    return nanos_to_millis(os::javaTimeNanos() - _last_safepoint_end_time_ns);
   }
 
-  static jlong end_of_last_safepoint_epoch_ms() {
-    return _last_safepoint_end_time_epoch_ms;
+  static jlong end_of_last_safepoint_ms() {
+    return nanos_to_millis(_last_safepoint_end_time_ns);
   }
 
   static jlong start_of_safepoint() {
--- a/src/hotspot/share/runtime/threadStatisticalInfo.hpp	Wed Jan 22 12:35:24 2020 -0800
+++ b/src/hotspot/share/runtime/threadStatisticalInfo.hpp	Fri Jan 17 00:52:10 2020 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2018 SAP SE. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -37,12 +37,11 @@
   uint64_t _define_class_count;
 
 public:
-  ThreadStatisticalInfo() : _start_time_stamp(os::javaTimeMillis()), _define_class_count(0) {}
-  uint64_t getStartTime() const             { return _start_time_stamp; }
-  uint64_t getDefineClassCount() const                    { return  _define_class_count; }
+  ThreadStatisticalInfo() : _start_time_stamp(os::javaTimeNanos()), _define_class_count(0) {}
+  uint64_t getDefineClassCount() const { return  _define_class_count; }
   void     setDefineClassCount(uint64_t defineClassCount) { _define_class_count = defineClassCount; }
-  void     incr_define_class_count()                      { _define_class_count += 1; }
-  uint64_t getElapsedTime() const           { return os::javaTimeMillis() - getStartTime(); }
+  void     incr_define_class_count() { _define_class_count += 1; }
+  uint64_t getElapsedTime() const { return nanos_to_millis(os::javaTimeNanos() - _start_time_stamp); }
 };
 
 #endif // SHARE_RUNTIME_THREADSTATISTICALINFO_HPP
--- a/src/hotspot/share/runtime/vmOperations.hpp	Wed Jan 22 12:35:24 2020 -0800
+++ b/src/hotspot/share/runtime/vmOperations.hpp	Fri Jan 17 00:52:10 2020 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -136,7 +136,7 @@
 
  private:
   Thread*         _calling_thread;
-  long            _timestamp;
+  uint64_t        _timestamp;
   VM_Operation*   _next;
   VM_Operation*   _prev;
 
@@ -150,8 +150,8 @@
   Thread* calling_thread() const                 { return _calling_thread; }
   void set_calling_thread(Thread* thread);
 
-  long timestamp() const              { return _timestamp; }
-  void set_timestamp(long timestamp)  { _timestamp = timestamp; }
+  uint64_t timestamp() const              { return _timestamp; }
+  void set_timestamp(uint64_t timestamp)  { _timestamp = timestamp; }
 
   // Called by VM thread - does in turn invoke doit(). Do not override this
   void evaluate();
--- a/src/hotspot/share/runtime/vmThread.cpp	Wed Jan 22 12:35:24 2020 -0800
+++ b/src/hotspot/share/runtime/vmThread.cpp	Fri Jan 17 00:52:10 2020 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -167,7 +167,7 @@
 void VMOperationTimeoutTask::task() {
   assert(AbortVMOnVMOperationTimeout, "only if enabled");
   if (is_armed()) {
-    jlong delay = (os::javaTimeMillis() - _arm_time);
+    jlong delay = nanos_to_millis(os::javaTimeNanos() - _arm_time);
     if (delay > AbortVMOnVMOperationTimeoutDelay) {
       fatal("VM operation took too long: " JLONG_FORMAT " ms (timeout: " INTX_FORMAT " ms)",
             delay, AbortVMOnVMOperationTimeoutDelay);
@@ -180,7 +180,7 @@
 }
 
 void VMOperationTimeoutTask::arm() {
-  _arm_time = os::javaTimeMillis();
+  _arm_time = os::javaTimeNanos();
   Atomic::release_store_fence(&_armed, 1);
 }
 
@@ -446,9 +446,9 @@
 
       // Stall time tracking code
       if (PrintVMQWaitTime && _cur_vm_operation != NULL) {
-        long stall = os::javaTimeMillis() - _cur_vm_operation->timestamp();
+        jlong stall = nanos_to_millis(os::javaTimeNanos() - _cur_vm_operation->timestamp());
         if (stall > 0)
-          tty->print_cr("%s stall: %ld",  _cur_vm_operation->name(), stall);
+          tty->print_cr("%s stall: " JLONG_FORMAT,  _cur_vm_operation->name(), stall);
       }
 
       while (!should_terminate() && _cur_vm_operation == NULL) {
@@ -640,7 +640,7 @@
       MonitorLocker ml(VMOperationQueue_lock, Mutex::_no_safepoint_check_flag);
       log_debug(vmthread)("Adding VM operation: %s", op->name());
       _vm_queue->add(op);
-      op->set_timestamp(os::javaTimeMillis());
+      op->set_timestamp(os::javaTimeNanos());
       ml.notify();
     }
     {
--- a/src/hotspot/share/services/gcNotifier.cpp	Wed Jan 22 12:35:24 2020 -0800
+++ b/src/hotspot/share/services/gcNotifier.cpp	Fri Jan 17 00:52:10 2020 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -49,6 +49,7 @@
   // stat is deallocated inside GCNotificationRequest
   GCStatInfo* stat = new(ResourceObj::C_HEAP, mtGC) GCStatInfo(num_pools);
   mgr->get_last_gc_stat(stat);
+  // timestamp is current time in ms
   GCNotificationRequest *request = new GCNotificationRequest(os::javaTimeMillis(),mgr,action,cause,stat);
   addRequest(request);
  }
--- a/src/hotspot/share/services/heapDumper.cpp	Wed Jan 22 12:35:24 2020 -0800
+++ b/src/hotspot/share/services/heapDumper.cpp	Fri Jan 17 00:52:10 2020 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1827,6 +1827,7 @@
   writer()->write_raw((void*)header, (int)strlen(header));
   writer()->write_u1(0); // terminator
   writer()->write_u4(oopSize);
+  // timestamp is current time in ms
   writer()->write_u8(os::javaTimeMillis());
 
   // HPROF_UTF8 records
--- a/src/hotspot/share/utilities/globalDefinitions.hpp	Wed Jan 22 12:35:24 2020 -0800
+++ b/src/hotspot/share/utilities/globalDefinitions.hpp	Fri Jan 17 00:52:10 2020 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -254,10 +254,22 @@
 const int MILLIUNITS    = 1000;         // milli units per base unit
 const int MICROUNITS    = 1000000;      // micro units per base unit
 const int NANOUNITS     = 1000000000;   // nano units per base unit
+const int NANOUNITS_PER_MILLIUNIT = NANOUNITS / MILLIUNITS;
 
 const jlong NANOSECS_PER_SEC      = CONST64(1000000000);
 const jint  NANOSECS_PER_MILLISEC = 1000000;
 
+
+// Unit conversion functions
+// The caller is responsible for considering overlow.
+
+inline int64_t nanos_to_millis(int64_t nanos) {
+  return nanos / NANOUNITS_PER_MILLIUNIT;
+}
+inline int64_t millis_to_nanos(int64_t millis) {
+  return millis * NANOUNITS_PER_MILLIUNIT;
+}
+
 // Proper units routines try to maintain at least three significant digits.
 // In worst case, it would print five significant digits with lower prefix.
 // G is close to MAX_SIZE on 32-bit platforms, so its product can easily overflow,
--- a/src/hotspot/share/utilities/ostream.cpp	Wed Jan 22 12:35:24 2020 -0800
+++ b/src/hotspot/share/utilities/ostream.cpp	Fri Jan 17 00:52:10 2020 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -659,9 +659,10 @@
     // Write XML header.
     xs->print_cr("<?xml version='1.0' encoding='UTF-8'?>");
     // (For now, don't bother to issue a DTD for this private format.)
+
+    // Calculate the start time of the log as ms since the epoch: this is
+    // the current time in ms minus the uptime in ms.
     jlong time_ms = os::javaTimeMillis() - tty->time_stamp().milliseconds();
-    // %%% Should be: jlong time_ms = os::start_time_milliseconds(), if
-    // we ever get round to introduce that method on the os class
     xs->head("hotspot_log version='%d %d'"
              " process='%d' time_ms='" INT64_FORMAT "'",
              LOG_MAJOR_VERSION, LOG_MINOR_VERSION,