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