package de.is24.util.monitoring.tools; import javax.management.MBeanServer; import java.io.OutputStream; import java.io.PrintWriter; import java.lang.Thread.State; import java.lang.management.GarbageCollectorMXBean; import java.lang.management.LockInfo; import java.lang.management.ManagementFactory; import java.lang.management.MemoryMXBean; import java.lang.management.MemoryPoolMXBean; 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.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; /** * A collection of Java Virtual Machine metrics. * This code was originally taken from de.is24.util.monitoring.tools.VirtualMachineMetrics */ public class VirtualMachineMBeans { private static final int MAX_STACK_TRACE_DEPTH = 100; private static final VirtualMachineMBeans INSTANCE = new VirtualMachineMBeans( ManagementFactory.getMemoryMXBean(), ManagementFactory.getMemoryPoolMXBeans(), ManagementFactory.getOperatingSystemMXBean(), ManagementFactory.getThreadMXBean(), ManagementFactory.getGarbageCollectorMXBeans(), ManagementFactory.getRuntimeMXBean(), ManagementFactory.getPlatformMBeanServer()); /** * The default instance of {@link VirtualMachineMBeans}. * * @return the default {@link VirtualMachineMBeans instance} */ public static VirtualMachineMBeans getInstance() { return INSTANCE; } private final MemoryMXBean memory; private final List<MemoryPoolMXBean> memoryPools; private final OperatingSystemMXBean os; private final ThreadMXBean threads; private final List<GarbageCollectorMXBean> garbageCollectors; private final RuntimeMXBean runtime; private final MBeanServer mBeanServer; VirtualMachineMBeans(MemoryMXBean memory, List<MemoryPoolMXBean> memoryPools, OperatingSystemMXBean os, ThreadMXBean threads, List<GarbageCollectorMXBean> garbageCollectors, RuntimeMXBean runtime, MBeanServer mBeanServer) { this.memory = memory; this.memoryPools = memoryPools; this.os = os; this.threads = threads; this.garbageCollectors = garbageCollectors; this.runtime = runtime; this.mBeanServer = mBeanServer; } public MemoryMXBean getMemory() { return memory; } public List<MemoryPoolMXBean> getMemoryPools() { return memoryPools; } public OperatingSystemMXBean getOs() { return os; } public ThreadMXBean getThreads() { return threads; } public List<GarbageCollectorMXBean> getGarbageCollectors() { return garbageCollectors; } public RuntimeMXBean getRuntime() { return runtime; } public MBeanServer getMBeanServer() { return mBeanServer; } /** * Returns the version of the currently-running jvm. * * @return the version of the currently-running jvm, eg "1.6.0_24" * @see <a href="http://java.sun.com/j2se/versioning_naming.html">J2SE SDK/JRE Version String * Naming Convention</a> */ public String getVersion() { return System.getProperty("java.runtime.version"); } /** * Returns the name of the currently-running jvm. * * @return the name of the currently-running jvm, eg "Java HotSpot(TM) Client VM" * @see <a href="http://download.oracle.com/javase/6/docs/api/java/lang/System.html#getProperties()">System.getProperties()</a> */ public String getName() { return System.getProperty("java.vm.name"); } /** * Returns a set of strings describing deadlocked threads, if any are deadlocked. * * @return a set of any deadlocked threads */ public Set<String> getDeadlockedThreads() { final long[] threadIds = threads.findDeadlockedThreads(); if (threadIds != null) { final Set<String> threads = new HashSet<String>(); for (ThreadInfo info : this.threads.getThreadInfo(threadIds, MAX_STACK_TRACE_DEPTH)) { final StringBuilder stackTrace = new StringBuilder(); for (StackTraceElement element : info.getStackTrace()) { stackTrace.append("\t at ").append(element.toString()).append('\n'); } threads.add( String.format( "%s locked on %s (owned by %s):\n%s", info.getThreadName(), info.getLockName(), info.getLockOwnerName(), stackTrace.toString())); } return Collections.unmodifiableSet(threads); } return Collections.emptySet(); } /** * Dumps all of the threads' current information to an output stream. * * @param out an output stream */ public void getThreadDump(OutputStream out) { final ThreadInfo[] threads = this.threads.dumpAllThreads(true, true); final PrintWriter writer = new PrintWriter(out, true); for (int ti = threads.length - 1; ti >= 0; ti--) { final ThreadInfo t = threads[ti]; writer.printf("%s id=%d state=%s", t.getThreadName(), t.getThreadId(), t.getThreadState()); final LockInfo lock = t.getLockInfo(); if ((lock != null) && (t.getThreadState() != State.BLOCKED)) { writer.printf("\n - waiting on <0x%08x> (a %s)", lock.getIdentityHashCode(), lock.getClassName()); writer.printf("\n - locked <0x%08x> (a %s)", lock.getIdentityHashCode(), lock.getClassName()); } else if ((lock != null) && (t.getThreadState() == State.BLOCKED)) { writer.printf("\n - waiting to lock <0x%08x> (a %s)", lock.getIdentityHashCode(), lock.getClassName()); } if (t.isSuspended()) { writer.print(" (suspended)"); } if (t.isInNative()) { writer.print(" (running in native)"); } writer.println(); if (t.getLockOwnerName() != null) { writer.printf(" owned by %s id=%d\n", t.getLockOwnerName(), t.getLockOwnerId()); } final StackTraceElement[] elements = t.getStackTrace(); final MonitorInfo[] monitors = t.getLockedMonitors(); for (int i = 0; i < elements.length; i++) { final StackTraceElement element = elements[i]; writer.printf(" at %s\n", element); for (int j = 1; j < monitors.length; j++) { final MonitorInfo monitor = monitors[j]; if (monitor.getLockedStackDepth() == i) { writer.printf(" - locked %s\n", monitor); } } } writer.println(); final LockInfo[] locks = t.getLockedSynchronizers(); if (locks.length > 0) { writer.printf(" Locked synchronizers: count = %d\n", locks.length); for (LockInfo l : locks) { writer.printf(" - %s\n", l); } writer.println(); } } writer.println(); writer.flush(); } }