/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License.
*/
// XXX TODO: Source code line length // XXX TODO: More JavaDoc // XXX Optional: Add support for com.sun.management specific mbean // (http://docs.oracle.com/javase/7/docs/jre/api/management/extension/index.html) // XXX Optional: Wire additional public static methods implemented here // to the manager (think about manager access roles!) // setLoggerLevel(), // setVerboseClassLoading(), // setThreadContentionMonitoringEnabled(), // setThreadCpuTimeEnabled(), // resetPeakThreadCount(), // setVerboseGarbageCollection() // gc(), // resetPeakUsage(), // setUsageThreshold(), // setCollectionUsageThreshold()
// XXX Not sure whether the following MBeans should better // be retrieved on demand, i.e. whether they can change // dynamically in the MBeanServer. privatestaticfinal PlatformLoggingMXBean loggingMXBean =
ManagementFactory.getPlatformMXBean(PlatformLoggingMXBean.class); privatestaticfinal MemoryMXBean memoryMXBean =
ManagementFactory.getMemoryMXBean(); privatestaticfinal List<GarbageCollectorMXBean> garbageCollectorMXBeans =
ManagementFactory.getGarbageCollectorMXBeans(); privatestaticfinal List<MemoryManagerMXBean> memoryManagerMXBeans =
ManagementFactory.getMemoryManagerMXBeans(); privatestaticfinal List<MemoryPoolMXBean> memoryPoolMXBeans =
ManagementFactory.getMemoryPoolMXBeans();
/** * Check whether thread contention monitoring is enabled. * * @return true if thread contention monitoring is enabled
*/ publicstaticboolean isThreadContentionMonitoringEnabled() { return threadMXBean.isThreadContentionMonitoringEnabled();
}
/** * Enable or disable thread contention monitoring via the ThreadMxMXBean. * * @param enable whether to enable thread contention monitoring
*/ publicstaticvoid setThreadContentionMonitoringEnabled(boolean enable) {
threadMXBean.setThreadContentionMonitoringEnabled(enable); boolean checkValue = threadMXBean.isThreadContentionMonitoringEnabled(); if (enable != checkValue) {
log.error("Could not set threadContentionMonitoringEnabled to " +
enable + ", got " + checkValue + " instead");
}
}
/** * Check whether thread cpu time measurement is enabled. * * @return true if thread cpu time measurement is enabled
*/ publicstaticboolean isThreadCpuTimeEnabled() { return threadMXBean.isThreadCpuTimeEnabled();
}
/** * Enable or disable thread cpu time measurement via the ThreadMxMXBean. * * @param enable whether to enable thread cpu time measurement
*/ publicstaticvoid setThreadCpuTimeEnabled(boolean enable) {
threadMXBean.setThreadCpuTimeEnabled(enable); boolean checkValue = threadMXBean.isThreadCpuTimeEnabled(); if (enable != checkValue) {
log.error("Could not set threadCpuTimeEnabled to " + enable + ", got " + checkValue + " instead");
}
}
/** * Set verbose class loading * * @param verbose whether to enable verbose class loading
*/ publicstaticvoid setVerboseClassLoading(boolean verbose) {
classLoadingMXBean.setVerbose(verbose); boolean checkValue = classLoadingMXBean.isVerbose(); if (verbose != checkValue) {
log.error("Could not set verbose class loading to " + verbose + ", got " + checkValue + " instead");
}
}
/** * Set logger level * * @param loggerName the name of the logger * @param levelName the level to set
*/ publicstaticvoid setLoggerLevel(String loggerName, String levelName) {
loggingMXBean.setLoggerLevel(loggerName, levelName);
String checkValue = loggingMXBean.getLoggerLevel(loggerName); if (!checkValue.equals(levelName)) {
log.error("Could not set logger level for logger '" +
loggerName + "' to '" + levelName + "', got '" + checkValue + "' instead");
}
}
/** * Set verbose garbage collection logging * * @param verbose whether to enable verbose gc logging
*/ publicstaticvoid setVerboseGarbageCollection(boolean verbose) {
memoryMXBean.setVerbose(verbose); boolean checkValue = memoryMXBean.isVerbose(); if (verbose != checkValue) {
log.error("Could not set verbose garbage collection logging to " + verbose + ", got " + checkValue + " instead");
}
}
/** * Reset peak memory usage data in MemoryPoolMXBean * * @param name name of the MemoryPoolMXBean or "all"
*/ publicstaticvoid resetPeakUsage(String name) { for (MemoryPoolMXBean mbean: memoryPoolMXBeans) { if (name.equals("all") || name.equals(mbean.getName())) {
mbean.resetPeakUsage();
}
}
}
/** * Set usage threshold in MemoryPoolMXBean * * @param name name of the MemoryPoolMXBean * @param threshold the threshold to set * @return true if setting the threshold succeeded
*/ publicstaticboolean setUsageThreshold(String name, long threshold) { for (MemoryPoolMXBean mbean: memoryPoolMXBeans) { if (name.equals(mbean.getName())) { try {
mbean.setUsageThreshold(threshold); returntrue;
} catch (IllegalArgumentException | UnsupportedOperationException ex) { // IGNORE
} returnfalse;
}
} returnfalse;
}
/** * Set collection usage threshold in MemoryPoolMXBean * * @param name name of the MemoryPoolMXBean * @param threshold the collection threshold to set * @return true if setting the threshold succeeded
*/ publicstaticboolean setCollectionUsageThreshold(String name, long threshold) { for (MemoryPoolMXBean mbean: memoryPoolMXBeans) { if (name.equals(mbean.getName())) { try {
mbean.setCollectionUsageThreshold(threshold); returntrue;
} catch (IllegalArgumentException | UnsupportedOperationException ex) { // IGNORE
} returnfalse;
}
} returnfalse;
}
/** * Formats the thread dump header for one thread. * * @param ti the ThreadInfo describing the thread * @return the formatted thread dump header
*/ privatestatic String getThreadDumpHeader(ThreadInfo ti) {
StringBuilder sb = new StringBuilder("\"" + ti.getThreadName() + "\"");
sb.append(" Id=" + ti.getThreadId());
sb.append(" cpu=" + threadMXBean.getThreadCpuTime(ti.getThreadId()) + " ns");
sb.append(" usr=" + threadMXBean.getThreadUserTime(ti.getThreadId()) + " ns");
sb.append(" blocked " + ti.getBlockedCount() + " for " +
ti.getBlockedTime() + " ms");
sb.append(" waited " + ti.getWaitedCount() + " for " +
ti.getWaitedTime() + " ms");
if (ti.isSuspended()) {
sb.append(" (suspended)");
} if (ti.isInNative()) {
sb.append(" (running in native)");
}
sb.append(CRLF);
sb.append(INDENT3 + "java.lang.Thread.State: " + ti.getThreadState());
sb.append(CRLF); return sb.toString();
}
/** * Formats the thread dump for one thread. * * @param ti the ThreadInfo describing the thread * @return the formatted thread dump
*/ privatestatic String getThreadDump(ThreadInfo ti) {
StringBuilder sb = new StringBuilder(getThreadDumpHeader(ti)); for (LockInfo li : ti.getLockedSynchronizers()) {
sb.append(INDENT2 + "locks " +
li.toString() + CRLF);
} boolean start = true;
StackTraceElement[] stes = ti.getStackTrace();
Object[] monitorDepths = new Object[stes.length];
MonitorInfo[] mis = ti.getLockedMonitors(); for (MonitorInfo monitorInfo : mis) {
monitorDepths[monitorInfo.getLockedStackDepth()] = monitorInfo;
} for (int i = 0; i < stes.length; i++) {
StackTraceElement ste = stes[i];
sb.append(INDENT2 + "at " + ste.toString() + CRLF); if (start) { if (ti.getLockName() != null) {
sb.append(INDENT2 + "- waiting on (a " +
ti.getLockName() + ")"); if (ti.getLockOwnerName() != null) {
sb.append(" owned by " + ti.getLockOwnerName() + " Id=" + ti.getLockOwnerId());
}
sb.append(CRLF);
}
start = false;
} if (monitorDepths[i] != null) {
MonitorInfo mi = (MonitorInfo)monitorDepths[i];
sb.append(INDENT2 + "- locked (a " + mi.toString() + ")"+ " index " + mi.getLockedStackDepth() + " frame " + mi.getLockedStackFrame().toString());
sb.append(CRLF);
}
} return sb.toString();
}
/** * Formats the thread dump for a list of threads. * * @param tinfos the ThreadInfo array describing the thread list * @return the formatted thread dump
*/ privatestatic String getThreadDump(ThreadInfo[] tinfos) {
StringBuilder sb = new StringBuilder(); for (ThreadInfo tinfo : tinfos) {
sb.append(getThreadDump(tinfo));
sb.append(CRLF);
} return sb.toString();
}
/** * Check if any threads are deadlocked. If any, print * the thread dump for those threads. * * @return a deadlock message and the formatted thread dump * of the deadlocked threads
*/ publicstatic String findDeadlock() {
ThreadInfo[] tinfos = null; long[] ids = threadMXBean.findDeadlockedThreads(); if (ids != null) {
tinfos = threadMXBean.getThreadInfo(threadMXBean.findDeadlockedThreads(), true, true); if (tinfos != null) {
StringBuilder sb = new StringBuilder("Deadlock found between the following threads:");
sb.append(CRLF);
sb.append(getThreadDump(tinfos)); return sb.toString();
}
} return"";
}
/** * Retrieves a formatted JVM thread dump. * The default StringManager will be used. * * @return the formatted JVM thread dump
*/ publicstatic String getThreadDump() { return getThreadDump(sm);
}
/** * Retrieves a formatted JVM thread dump. * The given list of locales will be used * to retrieve a StringManager. * * @param requestedLocales list of locales to use * @return the formatted JVM thread dump
*/ publicstatic String getThreadDump(Enumeration<Locale> requestedLocales) { return getThreadDump(
StringManager.getManager(PACKAGE, requestedLocales));
}
/** * Retrieve a JVM thread dump formatted * using the given StringManager. * * @param requestedSm the StringManager to use * @return the formatted JVM thread dump
*/ publicstatic String getThreadDump(StringManager requestedSm) {
StringBuilder sb = new StringBuilder();
/** * Format contents of a MemoryUsage object. * @param name a text prefix used in formatting * @param usage the MemoryUsage object to format * @return the formatted contents
*/ privatestatic String formatMemoryUsage(String name, MemoryUsage usage) { if (usage != null) {
StringBuilder sb = new StringBuilder();
sb.append(INDENT1 + name + " init: " + usage.getInit() + CRLF);
sb.append(INDENT1 + name + " used: " + usage.getUsed() + CRLF);
sb.append(INDENT1 + name + " committed: " + usage.getCommitted() + CRLF);
sb.append(INDENT1 + name + " max: " + usage.getMax() + CRLF); return sb.toString();
} return"";
}
/** * Retrieves a formatted JVM information text. * The default StringManager will be used. * * @return the formatted JVM information text
*/ publicstatic String getVMInfo() { return getVMInfo(sm);
}
/** * Retrieves a formatted JVM information text. * The given list of locales will be used * to retrieve a StringManager. * * @param requestedLocales list of locales to use * @return the formatted JVM information text
*/ publicstatic String getVMInfo(Enumeration<Locale> requestedLocales) { return getVMInfo(StringManager.getManager(PACKAGE, requestedLocales));
}
/** * Retrieve a JVM information text formatted * using the given StringManager. * * @param requestedSm the StringManager to use * @return the formatted JVM information text
*/ publicstatic String getVMInfo(StringManager requestedSm) {
StringBuilder sb = new StringBuilder();
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.