Mercurial > hg > openjdk > jdk8 > jdk
changeset 8773:0c75cc07d264
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
author | jbachorik |
---|---|
date | Sun, 10 Nov 2013 20:05:03 +0100 |
parents | 3add16c86970 |
children | 2525b91ca5a6 |
files | make/java/management/mapfile-vers makefiles/mapfiles/libmanagement/mapfile-vers src/share/classes/sun/management/RuntimeImpl.java src/share/classes/sun/management/VMManagement.java src/share/classes/sun/management/VMManagementImpl.java src/share/javavm/export/jmm.h src/share/native/sun/management/VMManagementImpl.c test/java/lang/management/RuntimeMXBean/UpTime.java |
diffstat | 8 files changed, 41 insertions(+), 18 deletions(-) [+] |
line wrap: on
line diff
--- a/make/java/management/mapfile-vers Sat Nov 09 14:30:03 2013 -0500 +++ b/make/java/management/mapfile-vers Sun Nov 10 20:05:03 2013 +0100 @@ -103,6 +103,7 @@ 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;
--- a/makefiles/mapfiles/libmanagement/mapfile-vers Sat Nov 09 14:30:03 2013 -0500 +++ b/makefiles/mapfiles/libmanagement/mapfile-vers Sun Nov 10 20:05:03 2013 +0100 @@ -103,6 +103,7 @@ 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;
--- a/src/share/classes/sun/management/RuntimeImpl.java Sat Nov 09 14:30:03 2013 -0500 +++ b/src/share/classes/sun/management/RuntimeImpl.java Sun Nov 10 20:05:03 2013 +0100 @@ -110,12 +110,7 @@ } 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() {
--- a/src/share/classes/sun/management/VMManagement.java Sat Nov 09 14:30:03 2013 -0500 +++ b/src/share/classes/sun/management/VMManagement.java Sun Nov 10 20:05:03 2013 +0100 @@ -71,6 +71,7 @@ public String getBootClassPath(); public List<String> getVmArguments(); public long getStartupTime(); + public long getUptime(); public int getAvailableProcessors(); // Compilation Subsystem
--- a/src/share/classes/sun/management/VMManagementImpl.java Sat Nov 09 14:30:03 2013 -0500 +++ b/src/share/classes/sun/management/VMManagementImpl.java Sun Nov 10 20:05:03 2013 +0100 @@ -179,6 +179,10 @@ return result; } + public long getUptime() { + return getUptime0(); + } + private List<String> vmArgs = null; public synchronized List<String> getVmArguments() { if (vmArgs == null) { @@ -192,6 +196,7 @@ public native String[] getVmArguments0(); public native long getStartupTime(); + private native long getUptime0(); public native int getAvailableProcessors(); // Compilation Subsystem
--- a/src/share/javavm/export/jmm.h Sat Nov 09 14:30:03 2013 -0500 +++ b/src/share/javavm/export/jmm.h Sun Nov 10 20:05:03 2013 +0100 @@ -78,6 +78,7 @@ 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 */
--- a/src/share/native/sun/management/VMManagementImpl.c Sat Nov 09 14:30:03 2013 -0500 +++ b/src/share/native/sun/management/VMManagementImpl.c Sun Nov 10 20:05:03 2013 +0100 @@ -200,6 +200,13 @@ 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)
--- a/test/java/lang/management/RuntimeMXBean/UpTime.java Sat Nov 09 14:30:03 2013 -0500 +++ b/test/java/lang/management/RuntimeMXBean/UpTime.java Sun Nov 10 20:05:03 2013 +0100 @@ -33,30 +33,34 @@ 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 @@ } } - 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 @@ System.out.println("Test passed."); } + + private static long System_milliTime() { + return System.nanoTime() / 1000000; // nanoseconds / milliseconds; + } } /*