View Javadoc
1   /*
2    * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.  Oracle designates this
8    * particular file as subject to the "Classpath" exception as provided
9    * by Oracle in the LICENSE file that accompanied this code.
10   *
11   * This code is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   * version 2 for more details (a copy is included in the LICENSE file that
15   * accompanied this code).
16   *
17   * You should have received a copy of the GNU General Public License version
18   * 2 along with this work; if not, write to the Free Software Foundation,
19   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20   *
21   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22   * or visit www.oracle.com if you need additional information or have any
23   * questions.
24   */
25  
26  package java.lang.management;
27  import javax.management.DynamicMBean;
28  import javax.management.MBeanServer;
29  import javax.management.MBeanServerConnection;
30  import javax.management.MBeanServerFactory;
31  import javax.management.MBeanServerPermission;
32  import javax.management.NotificationEmitter;
33  import javax.management.ObjectInstance;
34  import javax.management.ObjectName;
35  import javax.management.InstanceAlreadyExistsException;
36  import javax.management.InstanceNotFoundException;
37  import javax.management.MalformedObjectNameException;
38  import javax.management.MBeanRegistrationException;
39  import javax.management.NotCompliantMBeanException;
40  import javax.management.StandardEmitterMBean;
41  import javax.management.StandardMBean;
42  import java.util.Collections;
43  import java.util.List;
44  import java.util.Set;
45  import java.util.HashMap;
46  import java.util.HashSet;
47  import java.util.Map;
48  import java.security.AccessController;
49  import java.security.Permission;
50  import java.security.PrivilegedAction;
51  import java.security.PrivilegedActionException;
52  import java.security.PrivilegedExceptionAction;
53  import javax.management.JMX;
54  import sun.management.ManagementFactoryHelper;
55  
56  /**
57   * The {@code ManagementFactory} class is a factory class for getting
58   * managed beans for the Java platform.
59   * This class consists of static methods each of which returns
60   * one or more <i>platform MXBeans</i> representing
61   * the management interface of a component of the Java virtual
62   * machine.
63   *
64   * <h3><a name="MXBean">Platform MXBeans</a></h3>
65   * <p>
66   * A platform MXBean is a <i>managed bean</i> that
67   * conforms to the <a href="../../../javax/management/package-summary.html">JMX</a>
68   * Instrumentation Specification and only uses a set of basic data types.
69   * A JMX management application and the {@linkplain
70   * #getPlatformMBeanServer platform MBeanServer}
71   * can interoperate without requiring classes for MXBean specific
72   * data types.
73   * The data types being transmitted between the JMX connector
74   * server and the connector client are
75   * {@linkplain javax.management.openmbean.OpenType open types}
76   * and this allows interoperation across versions.
77   * See <a href="../../../javax/management/MXBean.html#MXBean-spec">
78   * the specification of MXBeans</a> for details.
79   *
80   * <a name="MXBeanNames"></a>
81   * <p>Each platform MXBean is a {@link PlatformManagedObject}
82   * and it has a unique
83   * {@link javax.management.ObjectName ObjectName} for
84   * registration in the platform {@code MBeanServer} as returned by
85   * by the {@link PlatformManagedObject#getObjectName getObjectName}
86   * method.
87   *
88   * <p>
89   * An application can access a platform MXBean in the following ways:
90   * <h4>1. Direct access to an MXBean interface</h4>
91   * <blockquote>
92   * <ul>
93   *     <li>Get an MXBean instance by calling the
94   *         {@link #getPlatformMXBean(Class) getPlatformMXBean} or
95   *         {@link #getPlatformMXBeans(Class) getPlatformMXBeans} method
96   *         and access the MXBean locally in the running
97   *         virtual machine.
98   *         </li>
99   *     <li>Construct an MXBean proxy instance that forwards the
100  *         method calls to a given {@link MBeanServer MBeanServer} by calling
101  *         the {@link #getPlatformMXBean(MBeanServerConnection, Class)} or
102  *         {@link #getPlatformMXBeans(MBeanServerConnection, Class)} method.
103  *         The {@link #newPlatformMXBeanProxy newPlatformMXBeanProxy} method
104  *         can also be used to construct an MXBean proxy instance of
105  *         a given {@code ObjectName}.
106  *         A proxy is typically constructed to remotely access
107  *         an MXBean of another running virtual machine.
108  *         </li>
109  * </ul>
110  * <h4>2. Indirect access to an MXBean interface via MBeanServer</h4>
111  * <ul>
112  *     <li>Go through the platform {@code MBeanServer} to access MXBeans
113  *         locally or a specific <tt>MBeanServerConnection</tt> to access
114  *         MXBeans remotely.
115  *         The attributes and operations of an MXBean use only
116  *         <em>JMX open types</em> which include basic data types,
117  *         {@link javax.management.openmbean.CompositeData CompositeData},
118  *         and {@link javax.management.openmbean.TabularData TabularData}
119  *         defined in
120  *         {@link javax.management.openmbean.OpenType OpenType}.
121  *         The mapping is specified in
122  *         the {@linkplain javax.management.MXBean MXBean} specification
123  *         for details.
124  *        </li>
125  * </ul>
126  * </blockquote>
127  *
128  * <p>
129  * The {@link #getPlatformManagementInterfaces getPlatformManagementInterfaces}
130  * method returns all management interfaces supported in the Java virtual machine
131  * including the standard management interfaces listed in the tables
132  * below as well as the management interfaces extended by the JDK implementation.
133  * <p>
134  * A Java virtual machine has a single instance of the following management
135  * interfaces:
136  *
137  * <blockquote>
138  * <table border summary="The list of Management Interfaces and their single instances">
139  * <tr>
140  * <th>Management Interface</th>
141  * <th>ObjectName</th>
142  * </tr>
143  * <tr>
144  * <td> {@link ClassLoadingMXBean} </td>
145  * <td> {@link #CLASS_LOADING_MXBEAN_NAME
146  *             java.lang:type=ClassLoading}</td>
147  * </tr>
148  * <tr>
149  * <td> {@link MemoryMXBean} </td>
150  * <td> {@link #MEMORY_MXBEAN_NAME
151  *             java.lang:type=Memory}</td>
152  * </tr>
153  * <tr>
154  * <td> {@link ThreadMXBean} </td>
155  * <td> {@link #THREAD_MXBEAN_NAME
156  *             java.lang:type=Threading}</td>
157  * </tr>
158  * <tr>
159  * <td> {@link RuntimeMXBean} </td>
160  * <td> {@link #RUNTIME_MXBEAN_NAME
161  *             java.lang:type=Runtime}</td>
162  * </tr>
163  * <tr>
164  * <td> {@link OperatingSystemMXBean} </td>
165  * <td> {@link #OPERATING_SYSTEM_MXBEAN_NAME
166  *             java.lang:type=OperatingSystem}</td>
167  * </tr>
168  * <tr>
169  * <td> {@link PlatformLoggingMXBean} </td>
170  * <td> {@link java.util.logging.LogManager#LOGGING_MXBEAN_NAME
171  *             java.util.logging:type=Logging}</td>
172  * </tr>
173  * </table>
174  * </blockquote>
175  *
176  * <p>
177  * A Java virtual machine has zero or a single instance of
178  * the following management interfaces.
179  *
180  * <blockquote>
181  * <table border summary="The list of Management Interfaces and their single instances">
182  * <tr>
183  * <th>Management Interface</th>
184  * <th>ObjectName</th>
185  * </tr>
186  * <tr>
187  * <td> {@link CompilationMXBean} </td>
188  * <td> {@link #COMPILATION_MXBEAN_NAME
189  *             java.lang:type=Compilation}</td>
190  * </tr>
191  * </table>
192  * </blockquote>
193  *
194  * <p>
195  * A Java virtual machine may have one or more instances of the following
196  * management interfaces.
197  * <blockquote>
198  * <table border summary="The list of Management Interfaces and their single instances">
199  * <tr>
200  * <th>Management Interface</th>
201  * <th>ObjectName</th>
202  * </tr>
203  * <tr>
204  * <td> {@link GarbageCollectorMXBean} </td>
205  * <td> {@link #GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE
206  *             java.lang:type=GarbageCollector}<tt>,name=</tt><i>collector's name</i></td>
207  * </tr>
208  * <tr>
209  * <td> {@link MemoryManagerMXBean} </td>
210  * <td> {@link #MEMORY_MANAGER_MXBEAN_DOMAIN_TYPE
211  *             java.lang:type=MemoryManager}<tt>,name=</tt><i>manager's name</i></td>
212  * </tr>
213  * <tr>
214  * <td> {@link MemoryPoolMXBean} </td>
215  * <td> {@link #MEMORY_POOL_MXBEAN_DOMAIN_TYPE
216  *             java.lang:type=MemoryPool}<tt>,name=</tt><i>pool's name</i></td>
217  * </tr>
218  * <tr>
219  * <td> {@link BufferPoolMXBean} </td>
220  * <td> {@code java.nio:type=BufferPool,name=}<i>pool name</i></td>
221  * </tr>
222  * </table>
223  * </blockquote>
224  *
225  * @see <a href="../../../javax/management/package-summary.html">
226  *      JMX Specification</a>
227  * @see <a href="package-summary.html#examples">
228  *      Ways to Access Management Metrics</a>
229  * @see javax.management.MXBean
230  *
231  * @author  Mandy Chung
232  * @since   1.5
233  */
234 public class ManagementFactory {
235     // A class with only static fields and methods.
236     private ManagementFactory() {};
237 
238     /**
239      * String representation of the
240      * <tt>ObjectName</tt> for the {@link ClassLoadingMXBean}.
241      */
242     public final static String CLASS_LOADING_MXBEAN_NAME =
243         "java.lang:type=ClassLoading";
244 
245     /**
246      * String representation of the
247      * <tt>ObjectName</tt> for the {@link CompilationMXBean}.
248      */
249     public final static String COMPILATION_MXBEAN_NAME =
250         "java.lang:type=Compilation";
251 
252     /**
253      * String representation of the
254      * <tt>ObjectName</tt> for the {@link MemoryMXBean}.
255      */
256     public final static String MEMORY_MXBEAN_NAME =
257         "java.lang:type=Memory";
258 
259     /**
260      * String representation of the
261      * <tt>ObjectName</tt> for the {@link OperatingSystemMXBean}.
262      */
263     public final static String OPERATING_SYSTEM_MXBEAN_NAME =
264         "java.lang:type=OperatingSystem";
265 
266     /**
267      * String representation of the
268      * <tt>ObjectName</tt> for the {@link RuntimeMXBean}.
269      */
270     public final static String RUNTIME_MXBEAN_NAME =
271         "java.lang:type=Runtime";
272 
273     /**
274      * String representation of the
275      * <tt>ObjectName</tt> for the {@link ThreadMXBean}.
276      */
277     public final static String THREAD_MXBEAN_NAME =
278         "java.lang:type=Threading";
279 
280     /**
281      * The domain name and the type key property in
282      * the <tt>ObjectName</tt> for a {@link GarbageCollectorMXBean}.
283      * The unique <tt>ObjectName</tt> for a <tt>GarbageCollectorMXBean</tt>
284      * can be formed by appending this string with
285      * "<tt>,name=</tt><i>collector's name</i>".
286      */
287     public final static String GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE =
288         "java.lang:type=GarbageCollector";
289 
290     /**
291      * The domain name and the type key property in
292      * the <tt>ObjectName</tt> for a {@link MemoryManagerMXBean}.
293      * The unique <tt>ObjectName</tt> for a <tt>MemoryManagerMXBean</tt>
294      * can be formed by appending this string with
295      * "<tt>,name=</tt><i>manager's name</i>".
296      */
297     public final static String MEMORY_MANAGER_MXBEAN_DOMAIN_TYPE=
298         "java.lang:type=MemoryManager";
299 
300     /**
301      * The domain name and the type key property in
302      * the <tt>ObjectName</tt> for a {@link MemoryPoolMXBean}.
303      * The unique <tt>ObjectName</tt> for a <tt>MemoryPoolMXBean</tt>
304      * can be formed by appending this string with
305      * <tt>,name=</tt><i>pool's name</i>.
306      */
307     public final static String MEMORY_POOL_MXBEAN_DOMAIN_TYPE=
308         "java.lang:type=MemoryPool";
309 
310     /**
311      * Returns the managed bean for the class loading system of
312      * the Java virtual machine.
313      *
314      * @return a {@link ClassLoadingMXBean} object for
315      * the Java virtual machine.
316      */
317     public static ClassLoadingMXBean getClassLoadingMXBean() {
318         return ManagementFactoryHelper.getClassLoadingMXBean();
319     }
320 
321     /**
322      * Returns the managed bean for the memory system of
323      * the Java virtual machine.
324      *
325      * @return a {@link MemoryMXBean} object for the Java virtual machine.
326      */
327     public static MemoryMXBean getMemoryMXBean() {
328         return ManagementFactoryHelper.getMemoryMXBean();
329     }
330 
331     /**
332      * Returns the managed bean for the thread system of
333      * the Java virtual machine.
334      *
335      * @return a {@link ThreadMXBean} object for the Java virtual machine.
336      */
337     public static ThreadMXBean getThreadMXBean() {
338         return ManagementFactoryHelper.getThreadMXBean();
339     }
340 
341     /**
342      * Returns the managed bean for the runtime system of
343      * the Java virtual machine.
344      *
345      * @return a {@link RuntimeMXBean} object for the Java virtual machine.
346 
347      */
348     public static RuntimeMXBean getRuntimeMXBean() {
349         return ManagementFactoryHelper.getRuntimeMXBean();
350     }
351 
352     /**
353      * Returns the managed bean for the compilation system of
354      * the Java virtual machine.  This method returns <tt>null</tt>
355      * if the Java virtual machine has no compilation system.
356      *
357      * @return a {@link CompilationMXBean} object for the Java virtual
358      *   machine or <tt>null</tt> if the Java virtual machine has
359      *   no compilation system.
360      */
361     public static CompilationMXBean getCompilationMXBean() {
362         return ManagementFactoryHelper.getCompilationMXBean();
363     }
364 
365     /**
366      * Returns the managed bean for the operating system on which
367      * the Java virtual machine is running.
368      *
369      * @return an {@link OperatingSystemMXBean} object for
370      * the Java virtual machine.
371      */
372     public static OperatingSystemMXBean getOperatingSystemMXBean() {
373         return ManagementFactoryHelper.getOperatingSystemMXBean();
374     }
375 
376     /**
377      * Returns a list of {@link MemoryPoolMXBean} objects in the
378      * Java virtual machine.
379      * The Java virtual machine can have one or more memory pools.
380      * It may add or remove memory pools during execution.
381      *
382      * @return a list of <tt>MemoryPoolMXBean</tt> objects.
383      *
384      */
385     public static List<MemoryPoolMXBean> getMemoryPoolMXBeans() {
386         return ManagementFactoryHelper.getMemoryPoolMXBeans();
387     }
388 
389     /**
390      * Returns a list of {@link MemoryManagerMXBean} objects
391      * in the Java virtual machine.
392      * The Java virtual machine can have one or more memory managers.
393      * It may add or remove memory managers during execution.
394      *
395      * @return a list of <tt>MemoryManagerMXBean</tt> objects.
396      *
397      */
398     public static List<MemoryManagerMXBean> getMemoryManagerMXBeans() {
399         return ManagementFactoryHelper.getMemoryManagerMXBeans();
400     }
401 
402 
403     /**
404      * Returns a list of {@link GarbageCollectorMXBean} objects
405      * in the Java virtual machine.
406      * The Java virtual machine may have one or more
407      * <tt>GarbageCollectorMXBean</tt> objects.
408      * It may add or remove <tt>GarbageCollectorMXBean</tt>
409      * during execution.
410      *
411      * @return a list of <tt>GarbageCollectorMXBean</tt> objects.
412      *
413      */
414     public static List<GarbageCollectorMXBean> getGarbageCollectorMXBeans() {
415         return ManagementFactoryHelper.getGarbageCollectorMXBeans();
416     }
417 
418     private static MBeanServer platformMBeanServer;
419     /**
420      * Returns the platform {@link javax.management.MBeanServer MBeanServer}.
421      * On the first call to this method, it first creates the platform
422      * {@code MBeanServer} by calling the
423      * {@link javax.management.MBeanServerFactory#createMBeanServer
424      * MBeanServerFactory.createMBeanServer}
425      * method and registers each platform MXBean in this platform
426      * {@code MBeanServer} with its
427      * {@link PlatformManagedObject#getObjectName ObjectName}.
428      * This method, in subsequent calls, will simply return the
429      * initially created platform {@code MBeanServer}.
430      * <p>
431      * MXBeans that get created and destroyed dynamically, for example,
432      * memory {@link MemoryPoolMXBean pools} and
433      * {@link MemoryManagerMXBean managers},
434      * will automatically be registered and deregistered into the platform
435      * {@code MBeanServer}.
436      * <p>
437      * If the system property {@code javax.management.builder.initial}
438      * is set, the platform {@code MBeanServer} creation will be done
439      * by the specified {@link javax.management.MBeanServerBuilder}.
440      * <p>
441      * It is recommended that this platform MBeanServer also be used
442      * to register other application managed beans
443      * besides the platform MXBeans.
444      * This will allow all MBeans to be published through the same
445      * {@code MBeanServer} and hence allow for easier network publishing
446      * and discovery.
447      * Name conflicts with the platform MXBeans should be avoided.
448      *
449      * @return the platform {@code MBeanServer}; the platform
450      *         MXBeans are registered into the platform {@code MBeanServer}
451      *         at the first time this method is called.
452      *
453      * @exception SecurityException if there is a security manager
454      * and the caller does not have the permission required by
455      * {@link javax.management.MBeanServerFactory#createMBeanServer}.
456      *
457      * @see javax.management.MBeanServerFactory
458      * @see javax.management.MBeanServerFactory#createMBeanServer
459      */
460     public static synchronized MBeanServer getPlatformMBeanServer() {
461         SecurityManager sm = System.getSecurityManager();
462         if (sm != null) {
463             Permission perm = new MBeanServerPermission("createMBeanServer");
464             sm.checkPermission(perm);
465         }
466 
467         if (platformMBeanServer == null) {
468             platformMBeanServer = MBeanServerFactory.createMBeanServer();
469             for (PlatformComponent pc : PlatformComponent.values()) {
470                 List<? extends PlatformManagedObject> list =
471                     pc.getMXBeans(pc.getMXBeanInterface());
472                 for (PlatformManagedObject o : list) {
473                     // Each PlatformComponent represents one management
474                     // interface. Some MXBean may extend another one.
475                     // The MXBean instances for one platform component
476                     // (returned by pc.getMXBeans()) might be also
477                     // the MXBean instances for another platform component.
478                     // e.g. com.sun.management.GarbageCollectorMXBean
479                     //
480                     // So need to check if an MXBean instance is registered
481                     // before registering into the platform MBeanServer
482                     if (!platformMBeanServer.isRegistered(o.getObjectName())) {
483                         addMXBean(platformMBeanServer, o);
484                     }
485                 }
486             }
487             HashMap<ObjectName, DynamicMBean> dynmbeans =
488                     ManagementFactoryHelper.getPlatformDynamicMBeans();
489             for (Map.Entry<ObjectName, DynamicMBean> e : dynmbeans.entrySet()) {
490                 addDynamicMBean(platformMBeanServer, e.getValue(), e.getKey());
491             }
492         }
493         return platformMBeanServer;
494     }
495 
496     /**
497      * Returns a proxy for a platform MXBean interface of a
498      * given <a href="#MXBeanNames">MXBean name</a>
499      * that forwards its method calls through the given
500      * <tt>MBeanServerConnection</tt>.
501      *
502      * <p>This method is equivalent to:
503      * <blockquote>
504      * {@link java.lang.reflect.Proxy#newProxyInstance
505      *        Proxy.newProxyInstance}<tt>(mxbeanInterface.getClassLoader(),
506      *        new Class[] { mxbeanInterface }, handler)</tt>
507      * </blockquote>
508      *
509      * where <tt>handler</tt> is an {@link java.lang.reflect.InvocationHandler
510      * InvocationHandler} to which method invocations to the MXBean interface
511      * are dispatched. This <tt>handler</tt> converts an input parameter
512      * from an MXBean data type to its mapped open type before forwarding
513      * to the <tt>MBeanServer</tt> and converts a return value from
514      * an MXBean method call through the <tt>MBeanServer</tt>
515      * from an open type to the corresponding return type declared in
516      * the MXBean interface.
517      *
518      * <p>
519      * If the MXBean is a notification emitter (i.e.,
520      * it implements
521      * {@link javax.management.NotificationEmitter NotificationEmitter}),
522      * both the <tt>mxbeanInterface</tt> and <tt>NotificationEmitter</tt>
523      * will be implemented by this proxy.
524      *
525      * <p>
526      * <b>Notes:</b>
527      * <ol>
528      * <li>Using an MXBean proxy is a convenience remote access to
529      * a platform MXBean of a running virtual machine.  All method
530      * calls to the MXBean proxy are forwarded to an
531      * <tt>MBeanServerConnection</tt> where
532      * {@link java.io.IOException IOException} may be thrown
533      * when the communication problem occurs with the connector server.
534      * An application remotely accesses the platform MXBeans using
535      * proxy should prepare to catch <tt>IOException</tt> as if
536      * accessing with the <tt>MBeanServerConnector</tt> interface.</li>
537      *
538      * <li>When a client application is designed to remotely access MXBeans
539      * for a running virtual machine whose version is different than
540      * the version on which the application is running,
541      * it should prepare to catch
542      * {@link java.io.InvalidObjectException InvalidObjectException}
543      * which is thrown when an MXBean proxy receives a name of an
544      * enum constant which is missing in the enum class loaded in
545      * the client application. </li>
546      *
547      * <li>{@link javax.management.MBeanServerInvocationHandler
548      * MBeanServerInvocationHandler} or its
549      * {@link javax.management.MBeanServerInvocationHandler#newProxyInstance
550      * newProxyInstance} method cannot be used to create
551      * a proxy for a platform MXBean. The proxy object created
552      * by <tt>MBeanServerInvocationHandler</tt> does not handle
553      * the properties of the platform MXBeans described in
554      * the <a href="#MXBean">class specification</a>.
555      *</li>
556      * </ol>
557      *
558      * @param connection the <tt>MBeanServerConnection</tt> to forward to.
559      * @param mxbeanName the name of a platform MXBean within
560      * <tt>connection</tt> to forward to. <tt>mxbeanName</tt> must be
561      * in the format of {@link ObjectName ObjectName}.
562      * @param mxbeanInterface the MXBean interface to be implemented
563      * by the proxy.
564      * @param <T> an {@code mxbeanInterface} type parameter
565      *
566      * @return a proxy for a platform MXBean interface of a
567      * given <a href="#MXBeanNames">MXBean name</a>
568      * that forwards its method calls through the given
569      * <tt>MBeanServerConnection</tt>, or {@code null} if not exist.
570      *
571      * @throws IllegalArgumentException if
572      * <ul>
573      * <li><tt>mxbeanName</tt> is not with a valid
574      *     {@link ObjectName ObjectName} format, or</li>
575      * <li>the named MXBean in the <tt>connection</tt> is
576      *     not a MXBean provided by the platform, or</li>
577      * <li>the named MXBean is not registered in the
578      *     <tt>MBeanServerConnection</tt>, or</li>
579      * <li>the named MXBean is not an instance of the given
580      *     <tt>mxbeanInterface</tt></li>
581      * </ul>
582      *
583      * @throws java.io.IOException if a communication problem
584      * occurred when accessing the <tt>MBeanServerConnection</tt>.
585      */
586     public static <T> T
587         newPlatformMXBeanProxy(MBeanServerConnection connection,
588                                String mxbeanName,
589                                Class<T> mxbeanInterface)
590             throws java.io.IOException {
591 
592         // Only allow MXBean interfaces from rt.jar loaded by the
593         // bootstrap class loader
594         final Class<?> cls = mxbeanInterface;
595         ClassLoader loader =
596             AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
597                 public ClassLoader run() {
598                     return cls.getClassLoader();
599                 }
600             });
601         if (!sun.misc.VM.isSystemDomainLoader(loader)) {
602             throw new IllegalArgumentException(mxbeanName +
603                 " is not a platform MXBean");
604         }
605 
606         try {
607             final ObjectName objName = new ObjectName(mxbeanName);
608             // skip the isInstanceOf check for LoggingMXBean
609             String intfName = mxbeanInterface.getName();
610             if (!connection.isInstanceOf(objName, intfName)) {
611                 throw new IllegalArgumentException(mxbeanName +
612                     " is not an instance of " + mxbeanInterface);
613             }
614 
615             final Class[] interfaces;
616             // check if the registered MBean is a notification emitter
617             boolean emitter = connection.isInstanceOf(objName, NOTIF_EMITTER);
618 
619             // create an MXBean proxy
620             return JMX.newMXBeanProxy(connection, objName, mxbeanInterface,
621                                       emitter);
622         } catch (InstanceNotFoundException|MalformedObjectNameException e) {
623             throw new IllegalArgumentException(e);
624         }
625     }
626 
627     /**
628      * Returns the platform MXBean implementing
629      * the given {@code mxbeanInterface} which is specified
630      * to have one single instance in the Java virtual machine.
631      * This method may return {@code null} if the management interface
632      * is not implemented in the Java virtual machine (for example,
633      * a Java virtual machine with no compilation system does not
634      * implement {@link CompilationMXBean});
635      * otherwise, this method is equivalent to calling:
636      * <pre>
637      *    {@link #getPlatformMXBeans(Class)
638      *      getPlatformMXBeans(mxbeanInterface)}.get(0);
639      * </pre>
640      *
641      * @param mxbeanInterface a management interface for a platform
642      *     MXBean with one single instance in the Java virtual machine
643      *     if implemented.
644      * @param <T> an {@code mxbeanInterface} type parameter
645      *
646      * @return the platform MXBean that implements
647      * {@code mxbeanInterface}, or {@code null} if not exist.
648      *
649      * @throws IllegalArgumentException if {@code mxbeanInterface}
650      * is not a platform management interface or
651      * not a singleton platform MXBean.
652      *
653      * @since 1.7
654      */
655     public static <T extends PlatformManagedObject>
656             T getPlatformMXBean(Class<T> mxbeanInterface) {
657         PlatformComponent pc = PlatformComponent.getPlatformComponent(mxbeanInterface);
658         if (pc == null)
659             throw new IllegalArgumentException(mxbeanInterface.getName() +
660                 " is not a platform management interface");
661         if (!pc.isSingleton())
662             throw new IllegalArgumentException(mxbeanInterface.getName() +
663                 " can have zero or more than one instances");
664 
665         return pc.getSingletonMXBean(mxbeanInterface);
666     }
667 
668     /**
669      * Returns the list of platform MXBeans implementing
670      * the given {@code mxbeanInterface} in the Java
671      * virtual machine.
672      * The returned list may contain zero, one, or more instances.
673      * The number of instances in the returned list is defined
674      * in the specification of the given management interface.
675      * The order is undefined and there is no guarantee that
676      * the list returned is in the same order as previous invocations.
677      *
678      * @param mxbeanInterface a management interface for a platform
679      *                        MXBean
680      * @param <T> an {@code mxbeanInterface} type parameter
681      *
682      * @return the list of platform MXBeans that implement
683      * {@code mxbeanInterface}.
684      *
685      * @throws IllegalArgumentException if {@code mxbeanInterface}
686      * is not a platform management interface.
687      *
688      * @since 1.7
689      */
690     public static <T extends PlatformManagedObject> List<T>
691             getPlatformMXBeans(Class<T> mxbeanInterface) {
692         PlatformComponent pc = PlatformComponent.getPlatformComponent(mxbeanInterface);
693         if (pc == null)
694             throw new IllegalArgumentException(mxbeanInterface.getName() +
695                 " is not a platform management interface");
696         return Collections.unmodifiableList(pc.getMXBeans(mxbeanInterface));
697     }
698 
699     /**
700      * Returns the platform MXBean proxy for
701      * {@code mxbeanInterface} which is specified to have one single
702      * instance in a Java virtual machine and the proxy will
703      * forward the method calls through the given {@code MBeanServerConnection}.
704      * This method may return {@code null} if the management interface
705      * is not implemented in the Java virtual machine being monitored
706      * (for example, a Java virtual machine with no compilation system
707      * does not implement {@link CompilationMXBean});
708      * otherwise, this method is equivalent to calling:
709      * <pre>
710      *     {@link #getPlatformMXBeans(MBeanServerConnection, Class)
711      *        getPlatformMXBeans(connection, mxbeanInterface)}.get(0);
712      * </pre>
713      *
714      * @param connection the {@code MBeanServerConnection} to forward to.
715      * @param mxbeanInterface a management interface for a platform
716      *     MXBean with one single instance in the Java virtual machine
717      *     being monitored, if implemented.
718      * @param <T> an {@code mxbeanInterface} type parameter
719      *
720      * @return the platform MXBean proxy for
721      * forwarding the method calls of the {@code mxbeanInterface}
722      * through the given {@code MBeanServerConnection},
723      * or {@code null} if not exist.
724      *
725      * @throws IllegalArgumentException if {@code mxbeanInterface}
726      * is not a platform management interface or
727      * not a singleton platform MXBean.
728      * @throws java.io.IOException if a communication problem
729      * occurred when accessing the {@code MBeanServerConnection}.
730      *
731      * @see #newPlatformMXBeanProxy
732      * @since 1.7
733      */
734     public static <T extends PlatformManagedObject>
735             T getPlatformMXBean(MBeanServerConnection connection,
736                                 Class<T> mxbeanInterface)
737         throws java.io.IOException
738     {
739         PlatformComponent pc = PlatformComponent.getPlatformComponent(mxbeanInterface);
740         if (pc == null)
741             throw new IllegalArgumentException(mxbeanInterface.getName() +
742                 " is not a platform management interface");
743         if (!pc.isSingleton())
744             throw new IllegalArgumentException(mxbeanInterface.getName() +
745                 " can have zero or more than one instances");
746         return pc.getSingletonMXBean(connection, mxbeanInterface);
747     }
748 
749     /**
750      * Returns the list of the platform MXBean proxies for
751      * forwarding the method calls of the {@code mxbeanInterface}
752      * through the given {@code MBeanServerConnection}.
753      * The returned list may contain zero, one, or more instances.
754      * The number of instances in the returned list is defined
755      * in the specification of the given management interface.
756      * The order is undefined and there is no guarantee that
757      * the list returned is in the same order as previous invocations.
758      *
759      * @param connection the {@code MBeanServerConnection} to forward to.
760      * @param mxbeanInterface a management interface for a platform
761      *                        MXBean
762      * @param <T> an {@code mxbeanInterface} type parameter
763      *
764      * @return the list of platform MXBean proxies for
765      * forwarding the method calls of the {@code mxbeanInterface}
766      * through the given {@code MBeanServerConnection}.
767      *
768      * @throws IllegalArgumentException if {@code mxbeanInterface}
769      * is not a platform management interface.
770      *
771      * @throws java.io.IOException if a communication problem
772      * occurred when accessing the {@code MBeanServerConnection}.
773      *
774      * @see #newPlatformMXBeanProxy
775      * @since 1.7
776      */
777     public static <T extends PlatformManagedObject>
778             List<T> getPlatformMXBeans(MBeanServerConnection connection,
779                                        Class<T> mxbeanInterface)
780         throws java.io.IOException
781     {
782         PlatformComponent pc = PlatformComponent.getPlatformComponent(mxbeanInterface);
783         if (pc == null) {
784             throw new IllegalArgumentException(mxbeanInterface.getName() +
785                 " is not a platform management interface");
786         }
787         return Collections.unmodifiableList(pc.getMXBeans(connection, mxbeanInterface));
788     }
789 
790     /**
791      * Returns the set of {@code Class} objects, subinterface of
792      * {@link PlatformManagedObject}, representing
793      * all management interfaces for
794      * monitoring and managing the Java platform.
795      *
796      * @return the set of {@code Class} objects, subinterface of
797      * {@link PlatformManagedObject} representing
798      * the management interfaces for
799      * monitoring and managing the Java platform.
800      *
801      * @since 1.7
802      */
803     public static Set<Class<? extends PlatformManagedObject>>
804            getPlatformManagementInterfaces()
805     {
806         Set<Class<? extends PlatformManagedObject>> result =
807             new HashSet<>();
808         for (PlatformComponent component: PlatformComponent.values()) {
809             result.add(component.getMXBeanInterface());
810         }
811         return Collections.unmodifiableSet(result);
812     }
813 
814     private static final String NOTIF_EMITTER =
815         "javax.management.NotificationEmitter";
816 
817     /**
818      * Registers an MXBean.
819      */
820     private static void addMXBean(final MBeanServer mbs, final PlatformManagedObject pmo) {
821         // Make DynamicMBean out of MXBean by wrapping it with a StandardMBean
822         try {
823             AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
824                 public Void run() throws InstanceAlreadyExistsException,
825                                          MBeanRegistrationException,
826                                          NotCompliantMBeanException {
827                     final DynamicMBean dmbean;
828                     if (pmo instanceof DynamicMBean) {
829                         dmbean = DynamicMBean.class.cast(pmo);
830                     } else if (pmo instanceof NotificationEmitter) {
831                         dmbean = new StandardEmitterMBean(pmo, null, true, (NotificationEmitter) pmo);
832                     } else {
833                         dmbean = new StandardMBean(pmo, null, true);
834                     }
835 
836                     mbs.registerMBean(dmbean, pmo.getObjectName());
837                     return null;
838                 }
839             });
840         } catch (PrivilegedActionException e) {
841             throw new RuntimeException(e.getException());
842         }
843     }
844 
845     /**
846      * Registers a DynamicMBean.
847      */
848     private static void addDynamicMBean(final MBeanServer mbs,
849                                         final DynamicMBean dmbean,
850                                         final ObjectName on) {
851         try {
852             AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
853                 @Override
854                 public Void run() throws InstanceAlreadyExistsException,
855                                          MBeanRegistrationException,
856                                          NotCompliantMBeanException {
857                     mbs.registerMBean(dmbean, on);
858                     return null;
859                 }
860             });
861         } catch (PrivilegedActionException e) {
862             throw new RuntimeException(e.getException());
863         }
864     }
865 }