提交 d012691a 编写于 作者: J jbachorik

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
上级 0d6a96d7
...@@ -103,6 +103,7 @@ SUNWprivate_1.1 { ...@@ -103,6 +103,7 @@ SUNWprivate_1.1 {
Java_sun_management_VMManagementImpl_getSafepointCount; Java_sun_management_VMManagementImpl_getSafepointCount;
Java_sun_management_VMManagementImpl_getSafepointSyncTime; Java_sun_management_VMManagementImpl_getSafepointSyncTime;
Java_sun_management_VMManagementImpl_getStartupTime; Java_sun_management_VMManagementImpl_getStartupTime;
Java_sun_management_VMManagementImpl_getUptime0;
Java_sun_management_VMManagementImpl_getTotalApplicationNonStoppedTime; Java_sun_management_VMManagementImpl_getTotalApplicationNonStoppedTime;
Java_sun_management_VMManagementImpl_getTotalClassCount; Java_sun_management_VMManagementImpl_getTotalClassCount;
Java_sun_management_VMManagementImpl_getTotalCompileTime; Java_sun_management_VMManagementImpl_getTotalCompileTime;
......
...@@ -103,6 +103,7 @@ SUNWprivate_1.1 { ...@@ -103,6 +103,7 @@ SUNWprivate_1.1 {
Java_sun_management_VMManagementImpl_getSafepointCount; Java_sun_management_VMManagementImpl_getSafepointCount;
Java_sun_management_VMManagementImpl_getSafepointSyncTime; Java_sun_management_VMManagementImpl_getSafepointSyncTime;
Java_sun_management_VMManagementImpl_getStartupTime; Java_sun_management_VMManagementImpl_getStartupTime;
Java_sun_management_VMManagementImpl_getUptime0;
Java_sun_management_VMManagementImpl_getTotalApplicationNonStoppedTime; Java_sun_management_VMManagementImpl_getTotalApplicationNonStoppedTime;
Java_sun_management_VMManagementImpl_getTotalClassCount; Java_sun_management_VMManagementImpl_getTotalClassCount;
Java_sun_management_VMManagementImpl_getTotalCompileTime; Java_sun_management_VMManagementImpl_getTotalCompileTime;
......
...@@ -110,12 +110,7 @@ class RuntimeImpl implements RuntimeMXBean { ...@@ -110,12 +110,7 @@ class RuntimeImpl implements RuntimeMXBean {
} }
public long getUptime() { public long getUptime() {
long current = System.currentTimeMillis(); return jvm.getUptime();
// 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);
} }
public long getStartTime() { public long getStartTime() {
......
...@@ -71,6 +71,7 @@ public interface VMManagement { ...@@ -71,6 +71,7 @@ public interface VMManagement {
public String getBootClassPath(); public String getBootClassPath();
public List<String> getVmArguments(); public List<String> getVmArguments();
public long getStartupTime(); public long getStartupTime();
public long getUptime();
public int getAvailableProcessors(); public int getAvailableProcessors();
// Compilation Subsystem // Compilation Subsystem
......
...@@ -179,6 +179,10 @@ class VMManagementImpl implements VMManagement { ...@@ -179,6 +179,10 @@ class VMManagementImpl implements VMManagement {
return result; return result;
} }
public long getUptime() {
return getUptime0();
}
private List<String> vmArgs = null; private List<String> vmArgs = null;
public synchronized List<String> getVmArguments() { public synchronized List<String> getVmArguments() {
if (vmArgs == null) { if (vmArgs == null) {
...@@ -192,6 +196,7 @@ class VMManagementImpl implements VMManagement { ...@@ -192,6 +196,7 @@ class VMManagementImpl implements VMManagement {
public native String[] getVmArguments0(); public native String[] getVmArguments0();
public native long getStartupTime(); public native long getStartupTime();
private native long getUptime0();
public native int getAvailableProcessors(); public native int getAvailableProcessors();
// Compilation Subsystem // Compilation Subsystem
......
...@@ -78,6 +78,7 @@ typedef enum { ...@@ -78,6 +78,7 @@ typedef enum {
JMM_COMPILE_TOTAL_TIME_MS = 8, /* Total accumulated time spent in compilation */ 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_TIME_MS = 9, /* Total accumulated time spent in collection */
JMM_GC_COUNT = 10, /* Total number of collections */ JMM_GC_COUNT = 10, /* Total number of collections */
JMM_JVM_UPTIME_MS = 11, /* The JVM uptime in milliseconds */
JMM_INTERNAL_ATTRIBUTE_INDEX = 100, JMM_INTERNAL_ATTRIBUTE_INDEX = 100,
JMM_CLASS_LOADED_BYTES = 101, /* Number of bytes loaded instance classes */ JMM_CLASS_LOADED_BYTES = 101, /* Number of bytes loaded instance classes */
......
...@@ -200,6 +200,13 @@ Java_sun_management_VMManagementImpl_getStartupTime ...@@ -200,6 +200,13 @@ Java_sun_management_VMManagementImpl_getStartupTime
JMM_JVM_INIT_DONE_TIME_MS); 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 JNIEXPORT jboolean JNICALL
Java_sun_management_VMManagementImpl_isThreadContentionMonitoringEnabled Java_sun_management_VMManagementImpl_isThreadContentionMonitoringEnabled
(JNIEnv *env, jobject dummy) (JNIEnv *env, jobject dummy)
......
...@@ -33,30 +33,34 @@ import java.lang.management.*; ...@@ -33,30 +33,34 @@ import java.lang.management.*;
public class UpTime { public class UpTime {
final static long DELAY = 5; // Seconds final static long DELAY = 5; // Seconds
final static long TIMEOUT = 30; // Minutes final static long TIMEOUT = 30; // Minutes
private static RuntimeMXBean metrics final static long MULTIPLIER = 1000; // millisecond ticks
private static final RuntimeMXBean metrics
= ManagementFactory.getRuntimeMXBean(); = ManagementFactory.getRuntimeMXBean();
public static void main(String argv[]) throws Exception { public static void main(String argv[]) throws Exception {
long jvmStartTime = metrics.getStartTime(); 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 metricsStart = metrics.getUptime();
long systemStartInner = System.currentTimeMillis(); long systemStartInner = System_milliTime();
// This JVM might have been running for some time if this test runs // 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. // 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 // If uptime is more than 30 minutes then it looks like a bug in
// the method // the method
if (testUptime > TIMEOUT * 60 * 1000) if (testUptime > TIMEOUT * 60 * MULTIPLIER)
throw new RuntimeException("Uptime of the JVM is more than 30 " throw new RuntimeException("Uptime of the JVM is more than 30 "
+ "minutes (" + "minutes ("
+ (metricsStart / 60 / 1000) + (metricsStart / 60 / MULTIPLIER)
+ " minutes)."); + " minutes).");
// Wait for DELAY seconds // Wait for DELAY seconds
Object o = new Object(); Object o = new Object();
while (System.currentTimeMillis() < systemStartInner + DELAY * 1000) { while (System_milliTime() < systemStartInner + DELAY * MULTIPLIER) {
synchronized (o) { synchronized (o) {
try { try {
o.wait(DELAY * 1000); o.wait(DELAY * 1000);
...@@ -67,23 +71,27 @@ public class UpTime { ...@@ -67,23 +71,27 @@ public class UpTime {
} }
} }
long systemEndInner = System.currentTimeMillis(); long systemEndInner = System_milliTime();
long metricsEnd = metrics.getUptime(); long metricsEnd = metrics.getUptime();
long systemEndOuter = System.currentTimeMillis(); long systemEndOuter = System_milliTime();
long systemDifferenceInner = systemEndInner - systemStartInner; long systemDifferenceInner = systemEndInner - systemStartInner;
long systemDifferenceOuter = systemEndOuter - systemStartOuter; long systemDifferenceOuter = systemEndOuter - systemStartOuter;
long metricsDifference = metricsEnd - metricsStart; long metricsDifference = metricsEnd - metricsStart;
// Check the flow of time in RuntimeMXBean.getUptime(). See the // Check the flow of time in RuntimeMXBean.getUptime(). See the
// picture below // picture below.
if (metricsDifference < systemDifferenceInner) // 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 " throw new RuntimeException("Flow of the time in "
+ "RuntimeMXBean.getUptime() (" + "RuntimeMXBean.getUptime() ("
+ metricsDifference + ") is slower than " + metricsDifference + ") is slower than "
+ " in system (" + systemDifferenceInner + " in system (" + systemDifferenceInner
+ ")"); + ")");
if (metricsDifference > systemDifferenceOuter) if (metricsDifference - systemDifferenceOuter > 1)
throw new RuntimeException("Flow of the time in " throw new RuntimeException("Flow of the time in "
+ "RuntimeMXBean.getUptime() (" + "RuntimeMXBean.getUptime() ("
+ metricsDifference + ") is faster than " + metricsDifference + ") is faster than "
...@@ -92,6 +100,10 @@ public class UpTime { ...@@ -92,6 +100,10 @@ public class UpTime {
System.out.println("Test passed."); System.out.println("Test passed.");
} }
private static long System_milliTime() {
return System.nanoTime() / 1000000; // nanoseconds / milliseconds;
}
} }
/* /*
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册