/* * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.sun.tools.visualvm.tools.jmx; import java.io.IOException; import java.lang.management.ClassLoadingMXBean; import java.lang.management.CompilationMXBean; import java.lang.management.GarbageCollectorMXBean; import static java.lang.management.ManagementFactory.*; import java.lang.management.MemoryMXBean; import java.lang.management.MemoryManagerMXBean; import java.lang.management.MemoryPoolMXBean; import java.lang.management.OperatingSystemMXBean; import java.lang.management.RuntimeMXBean; import java.lang.management.ThreadMXBean; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Set; import java.util.logging.Level; import java.util.logging.LogManager; import java.util.logging.Logger; import java.util.logging.LoggingMXBean; import javax.management.MBeanServerConnection; import javax.management.MalformedObjectNameException; import javax.management.ObjectName; /** * <p>The {@code JvmMXBeansFactory} class is a factory class that * allows to get instances of {@link JvmMXBeans} for a given * {@link MBeanServerConnection} or {@link JmxModel}.</p> * * <p>The factory methods allow to supply an interval value at which the * internal MBean cache will be automatically flushed and interested * {@link MBeanCacheListener}s notified.</p> * * <p>If the factory methods which do not take an interval value are used * then no MBean caching is performed at all.</p> * * @see CachedMBeanServerConnection * @see CachedMBeanServerConnectionFactory * * @author Luis-Miguel Alventosa */ public final class JvmMXBeansFactory { private JvmMXBeansFactory() { } /** * <p>Factory method for obtaining the {@link JvmMXBeans} for * the given {@link MBeanServerConnection}.</p> * * @param mbsc an MBeanServerConnection. * * @return a {@link JvmMXBeans} instance containing the MXBean * proxies for the Java platform MXBeans backed by the supplied * {@link MBeanServerConnection}. No MBean caching is applied on * the supplied {@link MBeanServerConnection}. */ public static JvmMXBeans getJvmMXBeans(MBeanServerConnection mbsc) { return new JvmMXBeansImpl(mbsc); } /** * <p>Factory method for obtaining the {@link JvmMXBeans} for * the given {@link MBeanServerConnection}.</p> * * <p>The MBeans in this {@link MBeanServerConnection} will be cached. * The MBean cache will be flushed at the given interval and the * interested {@link MBeanCacheListener}s will be notified.</p> * * @param mbsc an MBeanServerConnection. * @param interval the interval (in milliseconds) at which the MBean * cache is flushed. An interval equal to zero means no automatic flush * of the MBean cache. * * @return a {@link JvmMXBeans} instance containing the MXBean * proxies for the Java platform MXBeans backed by the supplied * {@link MBeanServerConnection}. MBean caching is enabled and * the cache is flushed at the end of every interval period. * * @throws IllegalArgumentException if the supplied interval is negative. */ public static JvmMXBeans getJvmMXBeans(MBeanServerConnection mbsc, int interval) throws IllegalArgumentException { if (interval < 0) { throw new IllegalArgumentException("interval cannot be negative"); // NOI18N } return new JvmMXBeansImpl(CachedMBeanServerConnectionFactory.getCachedMBeanServerConnection(mbsc, interval)); } /** * <p>Factory method for obtaining the {@link JvmMXBeans} for * the given {@link JmxModel}.</p> * * @param jmx a JmxModel. * * @return a {@link JvmMXBeans} instance containing the MXBean * proxies for the Java platform MXBeans backed by the supplied * {@link JmxModel}. No MBean caching is applied on the supplied * {@link JmxModel}. */ public static JvmMXBeans getJvmMXBeans(JmxModel jmx) { return new JvmMXBeansImpl(jmx.getMBeanServerConnection()); } /** * <p>Factory method for obtaining the {@link JvmMXBeans} for the given * {@link JmxModel}.</p> * * <p>The MBeans in this {@link JmxModel} will be cached. The MBean * cache will be flushed at the given interval and the interested * {@link MBeanCacheListener}s will be notified.</p> * * @param jmx a JmxModel. * @param interval the interval (in milliseconds) at which the MBean * cache is flushed. An interval equal to zero means no automatic flush * of the MBean cache. * * @return a {@link JvmMXBeans} instance containing the MXBean * proxies for the Java platform MXBeans backed by the supplied * {@link JmxModel}. MBean caching is enabled and the cache is * flushed at the end of every interval period. * * @throws IllegalArgumentException if the supplied interval is negative. */ public static JvmMXBeans getJvmMXBeans(JmxModel jmx, int interval) throws IllegalArgumentException { if (interval < 0) { throw new IllegalArgumentException("interval cannot be negative"); // NOI18N } return new JvmMXBeansImpl(CachedMBeanServerConnectionFactory.getCachedMBeanServerConnection(jmx.getMBeanServerConnection(), interval)); } /** * MXBean proxies for the Java platform MXBeans backed by the * supplied {@link MBeanServerConnection} or {@link JmxModel}. * * @author Luis-Miguel Alventosa */ static class JvmMXBeansImpl implements JvmMXBeans { protected MBeanServerConnection mbsc; private ClassLoadingMXBean classLoadingMXBean = null; private CompilationMXBean compilationMXBean = null; private LoggingMXBean loggingMXBean = null; private MemoryMXBean memoryMXBean = null; private OperatingSystemMXBean operatingSystemMXBean = null; private RuntimeMXBean runtimeMXBean = null; private ThreadMXBean threadMXBean = null; private List<GarbageCollectorMXBean> garbageCollectorMXBeans = null; private List<MemoryManagerMXBean> memoryManagerMXBeans = null; private List<MemoryPoolMXBean> memoryPoolMXBeans = null; private final static Logger LOGGER = Logger.getLogger(JvmMXBeansImpl.class.getName()); /** * Creates an instance of {@code JvmMXBeans} for the given * {@link MBeanServerConnection}. * * @param mbsc the {@link MBeanServerConnection} instance. */ public JvmMXBeansImpl(MBeanServerConnection mbsc) { this.mbsc = mbsc; } /** * Returns an MXBean proxy for the class loading system of the JVM. */ public synchronized ClassLoadingMXBean getClassLoadingMXBean() { if (mbsc != null && classLoadingMXBean == null) { classLoadingMXBean = getMXBean(CLASS_LOADING_MXBEAN_NAME, ClassLoadingMXBean.class); } return classLoadingMXBean; } /** * Returns an MXBean proxy for the compilation system of the JVM. */ public synchronized CompilationMXBean getCompilationMXBean() { if (mbsc != null && compilationMXBean == null) { compilationMXBean = getMXBean(COMPILATION_MXBEAN_NAME, CompilationMXBean.class); } return compilationMXBean; } /** * Returns an MXBean proxy for the logging system of the JVM. */ public synchronized LoggingMXBean getLoggingMXBean() { if (mbsc != null && loggingMXBean == null) { loggingMXBean = getMXBean(LogManager.LOGGING_MXBEAN_NAME, LoggingMXBean.class); } return loggingMXBean; } /** * Returns a collection of MXBean proxies for the garbage collectors of the JVM. */ public synchronized Collection<GarbageCollectorMXBean> getGarbageCollectorMXBeans() { // TODO: How to deal with changes to the list? if (mbsc != null && garbageCollectorMXBeans == null) { ObjectName gcName; try { gcName = new ObjectName(GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE + ",*"); } catch (MalformedObjectNameException e) { // Should never happen LOGGER.throwing(JvmMXBeansImpl.class.getName(), "getGarbageCollectorMXBeans", e); // NOI18N return null; } Set<ObjectName> mbeans; try { mbeans = mbsc.queryNames(gcName, null); } catch (Exception e) { LOGGER.throwing(JvmMXBeansImpl.class.getName(), "getGarbageCollectorMXBeans", e); // NOI18N return null; } if (mbeans != null) { garbageCollectorMXBeans = new ArrayList<GarbageCollectorMXBean>(); for (ObjectName on : mbeans) { String name = GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE + ",name=" + on.getKeyProperty("name"); // NOI18N try { GarbageCollectorMXBean mbean = newPlatformMXBeanProxy(mbsc, name, GarbageCollectorMXBean.class); garbageCollectorMXBeans.add(mbean); } catch (Exception e) { LOGGER.throwing(JvmMXBeansImpl.class.getName(), "getGarbageCollectorMXBeans", e); // NOI18N } } } } return garbageCollectorMXBeans; } /** * Returns a collection of MXBean proxies for the memory managers of the JVM. */ public synchronized Collection<MemoryManagerMXBean> getMemoryManagerMXBeans() { // TODO: How to deal with changes to the list? if (mbsc != null && memoryManagerMXBeans == null) { ObjectName managerName; try { managerName = new ObjectName(MEMORY_MANAGER_MXBEAN_DOMAIN_TYPE + ",*"); } catch (MalformedObjectNameException e) { // Should never happen LOGGER.throwing(JvmMXBeansImpl.class.getName(), "getMemoryManagerMXBeans", e); // NOI18N return null; } Set<ObjectName> mbeans; try { mbeans = mbsc.queryNames(managerName, null); } catch (Exception e) { LOGGER.throwing(JvmMXBeansImpl.class.getName(), "getMemoryManagerMXBeans", e); // NOI18N return null; } if (mbeans != null) { memoryManagerMXBeans = new ArrayList<MemoryManagerMXBean>(); for (ObjectName on : mbeans) { String name = MEMORY_MANAGER_MXBEAN_DOMAIN_TYPE + ",name=" + on.getKeyProperty("name"); // NOI18N try { MemoryManagerMXBean mbean = newPlatformMXBeanProxy(mbsc, name, MemoryManagerMXBean.class); memoryManagerMXBeans.add(mbean); } catch (Exception e) { LOGGER.throwing(JvmMXBeansImpl.class.getName(), "getMemoryManagerMXBeans", e); // NOI18N } } } } return memoryManagerMXBeans; } /** * Returns an MXBean proxy for the memory system of the JVM. */ public synchronized MemoryMXBean getMemoryMXBean() { if (mbsc != null && memoryMXBean == null) { memoryMXBean = getMXBean(MEMORY_MXBEAN_NAME, MemoryMXBean.class); } return memoryMXBean; } /** * Returns a collection of MXBean proxies for the memory pools of the JVM. */ public synchronized Collection<MemoryPoolMXBean> getMemoryPoolMXBeans() { // TODO: How to deal with changes to the list? if (mbsc != null && memoryPoolMXBeans == null) { ObjectName poolName; try { poolName = new ObjectName(MEMORY_POOL_MXBEAN_DOMAIN_TYPE + ",*"); } catch (MalformedObjectNameException e) { // Should never happen LOGGER.throwing(JvmMXBeansImpl.class.getName(), "getMemoryPoolMXBeans", e); // NOI18N return null; } Set<ObjectName> mbeans; try { mbeans = mbsc.queryNames(poolName, null); } catch (Exception e) { LOGGER.throwing(JvmMXBeansImpl.class.getName(), "getMemoryPoolMXBeans", e); // NOI18N return null; } if (mbeans != null) { memoryPoolMXBeans = new ArrayList<MemoryPoolMXBean>(); for (ObjectName on : mbeans) { String name = MEMORY_POOL_MXBEAN_DOMAIN_TYPE + ",name=" + on.getKeyProperty("name"); // NOI18N try { MemoryPoolMXBean mbean = newPlatformMXBeanProxy(mbsc, name, MemoryPoolMXBean.class); memoryPoolMXBeans.add(mbean); } catch (Exception e) { LOGGER.throwing(JvmMXBeansImpl.class.getName(), "getMemoryPoolMXBeans", e); // NOI18N } } } } return memoryPoolMXBeans; } /** * Returns an MXBean proxy for the operating system of the JVM. */ public synchronized OperatingSystemMXBean getOperatingSystemMXBean() { if (mbsc != null && operatingSystemMXBean == null) { operatingSystemMXBean = getMXBean(OPERATING_SYSTEM_MXBEAN_NAME, OperatingSystemMXBean.class); } return operatingSystemMXBean; } /** * Returns an MXBean proxy for the runtime system of the JVM. */ public synchronized RuntimeMXBean getRuntimeMXBean() { if (mbsc != null && runtimeMXBean == null) { runtimeMXBean = getMXBean(RUNTIME_MXBEAN_NAME, RuntimeMXBean.class); } return runtimeMXBean; } /** * Returns an MXBean proxy for the thread system of the JVM. */ public synchronized ThreadMXBean getThreadMXBean() { if (mbsc != null && threadMXBean == null) { threadMXBean = getMXBean(THREAD_MXBEAN_NAME, ThreadMXBean.class); } return threadMXBean; } /** * Generic method that returns an MXBean proxy for the given platform * MXBean identified by its ObjectName and which implements the supplied * interface. */ public <T> T getMXBean(ObjectName objectName, Class<T> interfaceClass) { return getMXBean(objectName.toString(), interfaceClass); } <T> T getMXBean(String objectNameStr, Class<T> interfaceClass) { if (mbsc != null) { try { return newPlatformMXBeanProxy(mbsc, objectNameStr, interfaceClass); } catch (IOException e) { LOGGER.throwing(JvmMXBeansImpl.class.getName(), "getMXBean", e); // NOI18N } catch (IllegalArgumentException iae) { LOGGER.log(Level.INFO, JvmMXBeansImpl.class.getName()+".getMXBean()", iae); // NOI18N } } return null; } public void addMBeanCacheListener(MBeanCacheListener listener) { if (mbsc instanceof CachedMBeanServerConnection) { ((CachedMBeanServerConnection) mbsc).addMBeanCacheListener(listener); } else { throw new UnsupportedOperationException("The underlying MBeanServerConnection does not support caching."); // NOI18N } } public void removeMBeanCacheListener(MBeanCacheListener listener) { if (mbsc instanceof CachedMBeanServerConnection) { ((CachedMBeanServerConnection) mbsc).removeMBeanCacheListener(listener); } else { throw new UnsupportedOperationException("The underlying MBeanServerConnection does not support caching."); // NOI18N } } public void flush() { if (mbsc instanceof CachedMBeanServerConnection) { ((CachedMBeanServerConnection) mbsc).flush(); } else { throw new UnsupportedOperationException("The underlying MBeanServerConnection does not support caching."); // NOI18N } } public int getInterval() { if (mbsc instanceof CachedMBeanServerConnection) { return ((CachedMBeanServerConnection) mbsc).getInterval(); } else { throw new UnsupportedOperationException("The underlying MBeanServerConnection does not support caching."); // NOI18N } } } }