| /* |
| * 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() |
| |
| package org.apache.tomcat.util; |
| |
| import java.lang.management.ClassLoadingMXBean; |
| import java.lang.management.CompilationMXBean; |
| import java.lang.management.GarbageCollectorMXBean; |
| import java.lang.management.LockInfo; |
| import java.lang.management.ManagementFactory; |
| import java.lang.management.MemoryMXBean; |
| import java.lang.management.MemoryManagerMXBean; |
| import java.lang.management.MemoryPoolMXBean; |
| import java.lang.management.MemoryUsage; |
| import java.lang.management.MonitorInfo; |
| import java.lang.management.OperatingSystemMXBean; |
| import java.lang.management.RuntimeMXBean; |
| import java.lang.management.ThreadInfo; |
| import java.lang.management.ThreadMXBean; |
| import java.text.SimpleDateFormat; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.Date; |
| import java.util.Enumeration; |
| import java.util.List; |
| import java.util.Locale; |
| import java.util.Map; |
| import java.util.logging.LogManager; |
| import java.util.logging.LoggingMXBean; |
| |
| import org.apache.tomcat.util.res.StringManager; |
| |
| public class Diagnostics { |
| |
| private static final String PACKAGE = "org.apache.tomcat.util"; |
| private static final StringManager sm = StringManager.getManager(PACKAGE); |
| |
| private static final String INDENT1 = " "; |
| private static final String INDENT2 = "\t"; |
| private static final String INDENT3 = " "; |
| private static final String CRLF = "\r\n"; |
| private static final String vminfoSystemProperty = "java.vm.info"; |
| |
| private static final org.apache.juli.logging.Log log= |
| org.apache.juli.logging.LogFactory.getLog(Diagnostics.class); |
| |
| private static final SimpleDateFormat timeformat = |
| new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); |
| |
| /* Some platform MBeans */ |
| private static final ClassLoadingMXBean classLoadingMXBean = |
| ManagementFactory.getClassLoadingMXBean(); |
| private static final CompilationMXBean compilationMXBean = |
| ManagementFactory.getCompilationMXBean(); |
| private static final OperatingSystemMXBean operatingSystemMXBean = |
| ManagementFactory.getOperatingSystemMXBean(); |
| private static final RuntimeMXBean runtimeMXBean = |
| ManagementFactory.getRuntimeMXBean(); |
| private static final ThreadMXBean threadMXBean = |
| ManagementFactory.getThreadMXBean(); |
| |
| // XXX Not sure whether the following MBeans should better |
| // be retrieved on demand, i.e. whether they can change |
| // dynamically in the MBeanServer. |
| private static final LoggingMXBean loggingMXBean = |
| LogManager.getLoggingMXBean(); |
| private static final MemoryMXBean memoryMXBean = |
| ManagementFactory.getMemoryMXBean(); |
| private static final List<GarbageCollectorMXBean> garbageCollectorMXBeans = |
| ManagementFactory.getGarbageCollectorMXBeans(); |
| private static final List<MemoryManagerMXBean> memoryManagerMXBeans = |
| ManagementFactory.getMemoryManagerMXBeans(); |
| private static final List<MemoryPoolMXBean> memoryPoolMXBeans = |
| ManagementFactory.getMemoryPoolMXBeans(); |
| |
| /** |
| * Check whether thread contention monitoring is enabled. |
| * |
| * @return true if thread contention monitoring is enabled |
| */ |
| public static boolean isThreadContentionMonitoringEnabled() { |
| return threadMXBean.isThreadContentionMonitoringEnabled(); |
| } |
| |
| /** |
| * Enable or disable thread contention monitoring via the ThreadMxMXBean. |
| * |
| * @param enable whether to enable thread contention monitoring |
| */ |
| public static void 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 |
| */ |
| public static boolean isThreadCpuTimeEnabled() { |
| return threadMXBean.isThreadCpuTimeEnabled(); |
| } |
| |
| /** |
| * Enable or disable thread cpu time measurement via the ThreadMxMXBean. |
| * |
| * @param enable whether to enable thread cpu time measurement |
| */ |
| public static void setThreadCpuTimeEnabled(boolean enable) { |
| threadMXBean.setThreadCpuTimeEnabled(enable); |
| boolean checkValue = threadMXBean.isThreadCpuTimeEnabled(); |
| if (enable != checkValue) { |
| log.error("Could not set threadCpuTimeEnabled to " + enable + |
| ", got " + checkValue + " instead"); |
| } |
| } |
| |
| /** |
| * Reset peak thread count in ThreadMXBean |
| */ |
| public static void resetPeakThreadCount() { |
| threadMXBean.resetPeakThreadCount(); |
| } |
| |
| /** |
| * Set verbose class loading |
| * |
| * @param verbose whether to enable verbose class loading |
| */ |
| public static void 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 |
| */ |
| public static void 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 |
| */ |
| public static void 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"); |
| } |
| } |
| |
| /** |
| * Initiate garbage collection via MX Bean |
| */ |
| public static void gc() { |
| memoryMXBean.gc(); |
| } |
| |
| /** |
| * Reset peak memory usage data in MemoryPoolMXBean |
| * |
| * @param name name of the MemoryPoolMXBean or "all" |
| */ |
| public static void 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 |
| */ |
| public static boolean setUsageThreshold(String name, long threshold) { |
| for (MemoryPoolMXBean mbean: memoryPoolMXBeans) { |
| if (name.equals(mbean.getName())) { |
| try { |
| mbean.setUsageThreshold(threshold); |
| return true; |
| } catch (IllegalArgumentException ex) { |
| // IGNORE |
| } catch (UnsupportedOperationException ex) { |
| // IGNORE |
| } |
| return false; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * 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 |
| */ |
| public static boolean setCollectionUsageThreshold(String name, long threshold) { |
| for (MemoryPoolMXBean mbean: memoryPoolMXBeans) { |
| if (name.equals(mbean.getName())) { |
| try { |
| mbean.setCollectionUsageThreshold(threshold); |
| return true; |
| } catch (IllegalArgumentException ex) { |
| // IGNORE |
| } catch (UnsupportedOperationException ex) { |
| // IGNORE |
| } |
| return false; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Formats the thread dump header for one thread. |
| * |
| * @param ti the ThreadInfo describing the thread |
| * @return the formatted thread dump header |
| */ |
| private static 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 |
| */ |
| private static 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 (int i = 0; i < mis.length; i++) { |
| monitorDepths[mis[i].getLockedStackDepth()] = mis[i]; |
| } |
| 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 |
| */ |
| private static 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 |
| */ |
| public static 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 |
| */ |
| public static 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 |
| */ |
| public static 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 |
| */ |
| public static String getThreadDump(StringManager requestedSm) { |
| StringBuilder sb = new StringBuilder(); |
| |
| synchronized(timeformat) { |
| sb.append(timeformat.format(new Date())); |
| } |
| sb.append(CRLF); |
| |
| sb.append(requestedSm.getString("diagnostics.threadDumpTitle")); |
| sb.append(" "); |
| sb.append(runtimeMXBean.getVmName()); |
| sb.append(" ("); |
| sb.append(runtimeMXBean.getVmVersion()); |
| String vminfo = System.getProperty(vminfoSystemProperty); |
| if (vminfo != null) { |
| sb.append(" " + vminfo); |
| } |
| sb.append("):" + CRLF); |
| sb.append(CRLF); |
| |
| ThreadInfo[] tis = threadMXBean.dumpAllThreads(true, true); |
| sb.append(getThreadDump(tis)); |
| |
| sb.append(findDeadlock()); |
| return sb.toString(); |
| } |
| |
| /** |
| * 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 |
| */ |
| private static 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 |
| */ |
| public static 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 |
| */ |
| public static 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 |
| */ |
| public static String getVMInfo(StringManager requestedSm) { |
| StringBuilder sb = new StringBuilder(); |
| |
| synchronized(timeformat) { |
| sb.append(timeformat.format(new Date())); |
| } |
| sb.append(CRLF); |
| |
| sb.append(requestedSm.getString("diagnostics.vmInfoRuntime")); |
| sb.append(":" + CRLF); |
| sb.append(INDENT1 + "vmName: " + runtimeMXBean.getVmName() + CRLF); |
| sb.append(INDENT1 + "vmVersion: " + runtimeMXBean.getVmVersion() + CRLF); |
| sb.append(INDENT1 + "vmVendor: " + runtimeMXBean.getVmVendor() + CRLF); |
| sb.append(INDENT1 + "specName: " + runtimeMXBean.getSpecName() + CRLF); |
| sb.append(INDENT1 + "specVersion: " + runtimeMXBean.getSpecVersion() + CRLF); |
| sb.append(INDENT1 + "specVendor: " + runtimeMXBean.getSpecVendor() + CRLF); |
| sb.append(INDENT1 + "managementSpecVersion: " + |
| runtimeMXBean.getManagementSpecVersion() + CRLF); |
| sb.append(INDENT1 + "name: " + runtimeMXBean.getName() + CRLF); |
| sb.append(INDENT1 + "startTime: " + runtimeMXBean.getStartTime() + CRLF); |
| sb.append(INDENT1 + "uptime: " + runtimeMXBean.getUptime() + CRLF); |
| sb.append(INDENT1 + "isBootClassPathSupported: " + |
| runtimeMXBean.isBootClassPathSupported() + CRLF); |
| sb.append(CRLF); |
| |
| sb.append(requestedSm.getString("diagnostics.vmInfoOs")); |
| sb.append(":" + CRLF); |
| sb.append(INDENT1 + "name: " + operatingSystemMXBean.getName() + CRLF); |
| sb.append(INDENT1 + "version: " + operatingSystemMXBean.getVersion() + CRLF); |
| sb.append(INDENT1 + "architecture: " + operatingSystemMXBean.getArch() + CRLF); |
| sb.append(INDENT1 + "availableProcessors: " + |
| operatingSystemMXBean.getAvailableProcessors() + CRLF); |
| sb.append(INDENT1 + "systemLoadAverage: " + |
| operatingSystemMXBean.getSystemLoadAverage() + CRLF); |
| sb.append(CRLF); |
| |
| sb.append(requestedSm.getString("diagnostics.vmInfoThreadMxBean")); |
| sb.append(":" + CRLF); |
| sb.append(INDENT1 + "isCurrentThreadCpuTimeSupported: " + |
| threadMXBean.isCurrentThreadCpuTimeSupported() + CRLF); |
| sb.append(INDENT1 + "isThreadCpuTimeSupported: " + |
| threadMXBean.isThreadCpuTimeSupported() + CRLF); |
| sb.append(INDENT1 + "isThreadCpuTimeEnabled: " + |
| threadMXBean.isThreadCpuTimeEnabled() + CRLF); |
| sb.append(INDENT1 + "isObjectMonitorUsageSupported: " + |
| threadMXBean.isObjectMonitorUsageSupported() + CRLF); |
| sb.append(INDENT1 + "isSynchronizerUsageSupported: " + |
| threadMXBean.isSynchronizerUsageSupported() + CRLF); |
| sb.append(INDENT1 + "isThreadContentionMonitoringSupported: " + |
| threadMXBean.isThreadContentionMonitoringSupported() + CRLF); |
| sb.append(INDENT1 + "isThreadContentionMonitoringEnabled: " + |
| threadMXBean.isThreadContentionMonitoringEnabled() + CRLF); |
| sb.append(CRLF); |
| |
| sb.append(requestedSm.getString("diagnostics.vmInfoThreadCounts")); |
| sb.append(":" + CRLF); |
| sb.append(INDENT1 + "daemon: " + threadMXBean.getDaemonThreadCount() + CRLF); |
| sb.append(INDENT1 + "total: " + threadMXBean.getThreadCount() + CRLF); |
| sb.append(INDENT1 + "peak: " + threadMXBean.getPeakThreadCount() + CRLF); |
| sb.append(INDENT1 + "totalStarted: " + |
| threadMXBean.getTotalStartedThreadCount() + CRLF); |
| sb.append(CRLF); |
| |
| sb.append(requestedSm.getString("diagnostics.vmInfoStartup")); |
| sb.append(":" + CRLF); |
| for (String arg: runtimeMXBean.getInputArguments()) { |
| sb.append(INDENT1 + arg + CRLF); |
| } |
| sb.append(CRLF); |
| |
| sb.append(requestedSm.getString("diagnostics.vmInfoPath")); |
| sb.append(":" + CRLF); |
| sb.append(INDENT1 + "bootClassPath: " + runtimeMXBean.getBootClassPath() + CRLF); |
| sb.append(INDENT1 + "classPath: " + runtimeMXBean.getClassPath() + CRLF); |
| sb.append(INDENT1 + "libraryPath: " + runtimeMXBean.getLibraryPath() + CRLF); |
| sb.append(CRLF); |
| |
| sb.append(requestedSm.getString("diagnostics.vmInfoClassLoading")); |
| sb.append(":" + CRLF); |
| sb.append(INDENT1 + "loaded: " + |
| classLoadingMXBean.getLoadedClassCount() + CRLF); |
| sb.append(INDENT1 + "unloaded: " + |
| classLoadingMXBean.getUnloadedClassCount() + CRLF); |
| sb.append(INDENT1 + "totalLoaded: " + |
| classLoadingMXBean.getTotalLoadedClassCount() + CRLF); |
| sb.append(INDENT1 + "isVerbose: " + |
| classLoadingMXBean.isVerbose() + CRLF); |
| sb.append(CRLF); |
| |
| sb.append(requestedSm.getString("diagnostics.vmInfoClassCompilation")); |
| sb.append(":" + CRLF); |
| sb.append(INDENT1 + "name: " + compilationMXBean.getName() + CRLF); |
| sb.append(INDENT1 + "totalCompilationTime: " + |
| compilationMXBean.getTotalCompilationTime() + CRLF); |
| sb.append(INDENT1 + "isCompilationTimeMonitoringSupported: " + |
| compilationMXBean.isCompilationTimeMonitoringSupported() + CRLF); |
| sb.append(CRLF); |
| |
| for (MemoryManagerMXBean mbean: memoryManagerMXBeans) { |
| sb.append(requestedSm.getString("diagnostics.vmInfoMemoryManagers", mbean.getName())); |
| sb.append(":" + CRLF); |
| sb.append(INDENT1 + "isValid: " + mbean.isValid() + CRLF); |
| sb.append(INDENT1 + "mbean.getMemoryPoolNames: " + CRLF); |
| String[] names = mbean.getMemoryPoolNames(); |
| Arrays.sort(names); |
| for (String name: names) { |
| sb.append(INDENT2 + name + CRLF); |
| } |
| sb.append(CRLF); |
| } |
| |
| for (GarbageCollectorMXBean mbean: garbageCollectorMXBeans) { |
| sb.append(requestedSm.getString("diagnostics.vmInfoGarbageCollectors", mbean.getName())); |
| sb.append(":" + CRLF); |
| sb.append(INDENT1 + "isValid: " + mbean.isValid() + CRLF); |
| sb.append(INDENT1 + "mbean.getMemoryPoolNames: " + CRLF); |
| String[] names = mbean.getMemoryPoolNames(); |
| Arrays.sort(names); |
| for (String name: names) { |
| sb.append(INDENT2 + name + CRLF); |
| } |
| sb.append(INDENT1 + "getCollectionCount: " + mbean.getCollectionCount() + CRLF); |
| sb.append(INDENT1 + "getCollectionTime: " + mbean.getCollectionTime() + CRLF); |
| sb.append(CRLF); |
| } |
| |
| sb.append(requestedSm.getString("diagnostics.vmInfoMemory")); |
| sb.append(":" + CRLF); |
| sb.append(INDENT1 + "isVerbose: " + memoryMXBean.isVerbose() + CRLF); |
| sb.append(INDENT1 + "getObjectPendingFinalizationCount: " + memoryMXBean.getObjectPendingFinalizationCount() + CRLF); |
| sb.append(formatMemoryUsage("heap", memoryMXBean.getHeapMemoryUsage())); |
| sb.append(formatMemoryUsage("non-heap", memoryMXBean.getNonHeapMemoryUsage())); |
| sb.append(CRLF); |
| |
| for (MemoryPoolMXBean mbean: memoryPoolMXBeans) { |
| sb.append(requestedSm.getString("diagnostics.vmInfoMemoryPools", mbean.getName())); |
| sb.append(":" + CRLF); |
| sb.append(INDENT1 + "isValid: " + mbean.isValid() + CRLF); |
| sb.append(INDENT1 + "getType: " + mbean.getType() + CRLF); |
| sb.append(INDENT1 + "mbean.getMemoryManagerNames: " + CRLF); |
| String[] names = mbean.getMemoryManagerNames(); |
| Arrays.sort(names); |
| for (String name: names) { |
| sb.append(INDENT2 + name + CRLF); |
| } |
| sb.append(INDENT1 + "isUsageThresholdSupported: " + mbean.isUsageThresholdSupported() + CRLF); |
| try { |
| sb.append(INDENT1 + "isUsageThresholdExceeded: " + mbean.isUsageThresholdExceeded() + CRLF); |
| } catch (UnsupportedOperationException ex) { |
| // IGNORE |
| } |
| sb.append(INDENT1 + "isCollectionUsageThresholdSupported: " + mbean.isCollectionUsageThresholdSupported() + CRLF); |
| try { |
| sb.append(INDENT1 + "isCollectionUsageThresholdExceeded: " + mbean.isCollectionUsageThresholdExceeded() + CRLF); |
| } catch (UnsupportedOperationException ex) { |
| // IGNORE |
| } |
| try { |
| sb.append(INDENT1 + "getUsageThreshold: " + mbean.getUsageThreshold() + CRLF); |
| } catch (UnsupportedOperationException ex) { |
| // IGNORE |
| } |
| try { |
| sb.append(INDENT1 + "getUsageThresholdCount: " + mbean.getUsageThresholdCount() + CRLF); |
| } catch (UnsupportedOperationException ex) { |
| // IGNORE |
| } |
| try { |
| sb.append(INDENT1 + "getCollectionUsageThreshold: " + mbean.getCollectionUsageThreshold() + CRLF); |
| } catch (UnsupportedOperationException ex) { |
| // IGNORE |
| } |
| try { |
| sb.append(INDENT1 + "getCollectionUsageThresholdCount: " + mbean.getCollectionUsageThresholdCount() + CRLF); |
| } catch (UnsupportedOperationException ex) { |
| // IGNORE |
| } |
| sb.append(formatMemoryUsage("current", mbean.getUsage())); |
| sb.append(formatMemoryUsage("collection", mbean.getCollectionUsage())); |
| sb.append(formatMemoryUsage("peak", mbean.getPeakUsage())); |
| sb.append(CRLF); |
| } |
| |
| |
| sb.append(requestedSm.getString("diagnostics.vmInfoSystem")); |
| sb.append(":" + CRLF); |
| Map<String,String> props = runtimeMXBean.getSystemProperties(); |
| ArrayList<String> keys = new ArrayList<>(props.keySet()); |
| Collections.sort(keys); |
| for (String prop: keys) { |
| sb.append(INDENT1 + prop + ": " + props.get(prop) + CRLF); |
| } |
| sb.append(CRLF); |
| |
| sb.append(requestedSm.getString("diagnostics.vmInfoLogger")); |
| sb.append(":" + CRLF); |
| List<String> loggers = loggingMXBean.getLoggerNames(); |
| Collections.sort(loggers); |
| for (String logger: loggers) { |
| sb.append(INDENT1 + logger + |
| ": level=" + loggingMXBean.getLoggerLevel(logger) + |
| ", parent=" + loggingMXBean.getParentLoggerName(logger) + CRLF); |
| } |
| sb.append(CRLF); |
| |
| return sb.toString(); |
| } |
| } |