在jdk中一個類可以獲得gc的信息:
public static void main(String[] args) {
List<GarbageCollectorMXBean> garbageCollectorMXBeans = ManagementFactory.getGarbageCollectorMXBeans();
for (GarbageCollectorMXBean garbageCollectorMXBean : garbageCollectorMXBeans) {
System.out.println(garbageCollectorMXBean.getName() + "# time: " + garbageCollectorMXBean.getCollectionTime() + ", count: " + garbageCollectorMXBean.getCollectionCount());
}
}
在hadoop-common.jar中,有個JvmPauseMonitor$Monitor類,它能監控jvm暫停時間:
private class Monitor implements Runnable {
@Override
public void run() {
StopWatch sw = new StopWatch();
Map<String, GcTimes> gcTimesBeforeSleep = getGcTimes(); // 用ManagementFactory.getGarbageCollectorMXBeans()收集得到 name:GcTime的信息
while (shouldRun) {
sw.reset().start();
try {
Thread.sleep(SLEEP_INTERVAL_MS);
} catch (InterruptedException ie) {
return;
}
long extraSleepTime = sw.now(TimeUnit.MILLISECONDS) - SLEEP_INTERVAL_MS; // 關鍵在這里,減去自己sleep的時間,大約等於系統暫停的時間(因為還有run方法執行其他代碼的時間)
Map<String, GcTimes> gcTimesAfterSleep = getGcTimes();
if (extraSleepTime > warnThresholdMs) { // 達到warn的閾值則打印警告
++numGcWarnThresholdExceeded;
LOG.warn(formatMessage(
extraSleepTime, gcTimesAfterSleep, gcTimesBeforeSleep));
} else if (extraSleepTime > infoThresholdMs) {
++numGcInfoThresholdExceeded;
LOG.info(formatMessage(
extraSleepTime, gcTimesAfterSleep, gcTimesBeforeSleep));
}
totalGcExtraSleepTime += extraSleepTime; // 記錄jvm暫停的時間(大約)
gcTimesBeforeSleep = gcTimesAfterSleep;
}
}
}
