From d012691ac92d9d40478f17522b8990f0fb8a4a1f Mon Sep 17 00:00:00 2001 From: jbachorik Date: Sun, 10 Nov 2013 20:05:03 +0100 Subject: [PATCH] 6523160: RuntimeMXBean.getUptime() returns negative values Summary: RuntimeMXBean.getUptime() should be based on HR timers rather than on the OS time Reviewed-by: dholmes, sla --- make/java/management/mapfile-vers | 1 + makefiles/mapfiles/libmanagement/mapfile-vers | 1 + .../classes/sun/management/RuntimeImpl.java | 7 +--- .../classes/sun/management/VMManagement.java | 1 + .../sun/management/VMManagementImpl.java | 5 +++ src/share/javavm/export/jmm.h | 1 + .../native/sun/management/VMManagementImpl.c | 7 ++++ .../lang/management/RuntimeMXBean/UpTime.java | 36 ++++++++++++------- 8 files changed, 41 insertions(+), 18 deletions(-) diff --git a/make/java/management/mapfile-vers b/make/java/management/mapfile-vers index 0ea2ab4eb..1cf52a8c7 100644 --- a/make/java/management/mapfile-vers +++ b/make/java/management/mapfile-vers @@ -103,6 +103,7 @@ SUNWprivate_1.1 { Java_sun_management_VMManagementImpl_getSafepointCount; Java_sun_management_VMManagementImpl_getSafepointSyncTime; Java_sun_management_VMManagementImpl_getStartupTime; + Java_sun_management_VMManagementImpl_getUptime0; Java_sun_management_VMManagementImpl_getTotalApplicationNonStoppedTime; Java_sun_management_VMManagementImpl_getTotalClassCount; Java_sun_management_VMManagementImpl_getTotalCompileTime; diff --git a/makefiles/mapfiles/libmanagement/mapfile-vers b/makefiles/mapfiles/libmanagement/mapfile-vers index 6e093a334..218dd3e3e 100644 --- a/makefiles/mapfiles/libmanagement/mapfile-vers +++ b/makefiles/mapfiles/libmanagement/mapfile-vers @@ -103,6 +103,7 @@ SUNWprivate_1.1 { Java_sun_management_VMManagementImpl_getSafepointCount; Java_sun_management_VMManagementImpl_getSafepointSyncTime; Java_sun_management_VMManagementImpl_getStartupTime; + Java_sun_management_VMManagementImpl_getUptime0; Java_sun_management_VMManagementImpl_getTotalApplicationNonStoppedTime; Java_sun_management_VMManagementImpl_getTotalClassCount; Java_sun_management_VMManagementImpl_getTotalCompileTime; diff --git a/src/share/classes/sun/management/RuntimeImpl.java b/src/share/classes/sun/management/RuntimeImpl.java index 2e947cc03..c0abdb744 100644 --- a/src/share/classes/sun/management/RuntimeImpl.java +++ b/src/share/classes/sun/management/RuntimeImpl.java @@ -110,12 +110,7 @@ class RuntimeImpl implements RuntimeMXBean { } public long getUptime() { - long current = System.currentTimeMillis(); - - // TODO: If called from client side when we support - // MBean proxy to read performance counters from shared memory, - // need to check if the monitored VM exitd. - return (current - vmStartupTime); + return jvm.getUptime(); } public long getStartTime() { diff --git a/src/share/classes/sun/management/VMManagement.java b/src/share/classes/sun/management/VMManagement.java index a02f828ed..f4445f022 100644 --- a/src/share/classes/sun/management/VMManagement.java +++ b/src/share/classes/sun/management/VMManagement.java @@ -71,6 +71,7 @@ public interface VMManagement { public String getBootClassPath(); public List getVmArguments(); public long getStartupTime(); + public long getUptime(); public int getAvailableProcessors(); // Compilation Subsystem diff --git a/src/share/classes/sun/management/VMManagementImpl.java b/src/share/classes/sun/management/VMManagementImpl.java index 46e0285e6..c5d050542 100644 --- a/src/share/classes/sun/management/VMManagementImpl.java +++ b/src/share/classes/sun/management/VMManagementImpl.java @@ -179,6 +179,10 @@ class VMManagementImpl implements VMManagement { return result; } + public long getUptime() { + return getUptime0(); + } + private List vmArgs = null; public synchronized List getVmArguments() { if (vmArgs == null) { @@ -192,6 +196,7 @@ class VMManagementImpl implements VMManagement { public native String[] getVmArguments0(); public native long getStartupTime(); + private native long getUptime0(); public native int getAvailableProcessors(); // Compilation Subsystem diff --git a/src/share/javavm/export/jmm.h b/src/share/javavm/export/jmm.h index e017e5a02..3f938e250 100644 --- a/src/share/javavm/export/jmm.h +++ b/src/share/javavm/export/jmm.h @@ -78,6 +78,7 @@ typedef enum { JMM_COMPILE_TOTAL_TIME_MS = 8, /* Total accumulated time spent in compilation */ JMM_GC_TIME_MS = 9, /* Total accumulated time spent in collection */ JMM_GC_COUNT = 10, /* Total number of collections */ + JMM_JVM_UPTIME_MS = 11, /* The JVM uptime in milliseconds */ JMM_INTERNAL_ATTRIBUTE_INDEX = 100, JMM_CLASS_LOADED_BYTES = 101, /* Number of bytes loaded instance classes */ diff --git a/src/share/native/sun/management/VMManagementImpl.c b/src/share/native/sun/management/VMManagementImpl.c index 27784e5dd..1aa09d2c4 100644 --- a/src/share/native/sun/management/VMManagementImpl.c +++ b/src/share/native/sun/management/VMManagementImpl.c @@ -200,6 +200,13 @@ Java_sun_management_VMManagementImpl_getStartupTime JMM_JVM_INIT_DONE_TIME_MS); } +JNIEXPORT jlong JNICALL +Java_sun_management_VMManagementImpl_getUptime0 + (JNIEnv *env, jobject dummy) +{ + return jmm_interface->GetLongAttribute(env, NULL, JMM_JVM_UPTIME_MS); +} + JNIEXPORT jboolean JNICALL Java_sun_management_VMManagementImpl_isThreadContentionMonitoringEnabled (JNIEnv *env, jobject dummy) diff --git a/test/java/lang/management/RuntimeMXBean/UpTime.java b/test/java/lang/management/RuntimeMXBean/UpTime.java index ac332caf2..5bfe094d8 100644 --- a/test/java/lang/management/RuntimeMXBean/UpTime.java +++ b/test/java/lang/management/RuntimeMXBean/UpTime.java @@ -33,30 +33,34 @@ import java.lang.management.*; public class UpTime { final static long DELAY = 5; // Seconds final static long TIMEOUT = 30; // Minutes - private static RuntimeMXBean metrics + final static long MULTIPLIER = 1000; // millisecond ticks + + private static final RuntimeMXBean metrics = ManagementFactory.getRuntimeMXBean(); public static void main(String argv[]) throws Exception { long jvmStartTime = metrics.getStartTime(); - long systemStartOuter = System.currentTimeMillis(); + // this will get an aproximate JVM uptime before starting this test + long jvmUptime = System.currentTimeMillis() - jvmStartTime; + long systemStartOuter = System_milliTime(); long metricsStart = metrics.getUptime(); - long systemStartInner = System.currentTimeMillis(); + long systemStartInner = System_milliTime(); // This JVM might have been running for some time if this test runs // in samevm mode. The sanity check should apply to the test uptime. - long testUptime = metricsStart - (systemStartOuter - jvmStartTime); + long testUptime = metricsStart - jvmUptime; // If uptime is more than 30 minutes then it looks like a bug in // the method - if (testUptime > TIMEOUT * 60 * 1000) + if (testUptime > TIMEOUT * 60 * MULTIPLIER) throw new RuntimeException("Uptime of the JVM is more than 30 " + "minutes (" - + (metricsStart / 60 / 1000) + + (metricsStart / 60 / MULTIPLIER) + " minutes)."); // Wait for DELAY seconds Object o = new Object(); - while (System.currentTimeMillis() < systemStartInner + DELAY * 1000) { + while (System_milliTime() < systemStartInner + DELAY * MULTIPLIER) { synchronized (o) { try { o.wait(DELAY * 1000); @@ -67,23 +71,27 @@ public class UpTime { } } - long systemEndInner = System.currentTimeMillis(); + long systemEndInner = System_milliTime(); long metricsEnd = metrics.getUptime(); - long systemEndOuter = System.currentTimeMillis(); + long systemEndOuter = System_milliTime(); long systemDifferenceInner = systemEndInner - systemStartInner; long systemDifferenceOuter = systemEndOuter - systemStartOuter; long metricsDifference = metricsEnd - metricsStart; // Check the flow of time in RuntimeMXBean.getUptime(). See the - // picture below - if (metricsDifference < systemDifferenceInner) + // picture below. + // The measured times can be off by 1 due to conversions from + // nanoseconds to milliseconds, using different channels to read the + // HR timer and rounding error. Bigger difference will make the test + // fail. + if (metricsDifference - systemDifferenceInner < -1) throw new RuntimeException("Flow of the time in " + "RuntimeMXBean.getUptime() (" + metricsDifference + ") is slower than " + " in system (" + systemDifferenceInner + ")"); - if (metricsDifference > systemDifferenceOuter) + if (metricsDifference - systemDifferenceOuter > 1) throw new RuntimeException("Flow of the time in " + "RuntimeMXBean.getUptime() (" + metricsDifference + ") is faster than " @@ -92,6 +100,10 @@ public class UpTime { System.out.println("Test passed."); } + + private static long System_milliTime() { + return System.nanoTime() / 1000000; // nanoseconds / milliseconds; + } } /* -- GitLab