1 /*
   2  * Copyright (c) 2008, 2012, 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 
  28 import java.util.ArrayList;
  29 import java.util.Collections;
  30 import java.util.List;
  31 import java.util.HashSet;
  32 import java.util.HashMap;
  33 import java.util.Map;
  34 import java.util.Set;
  35 import javax.management.MBeanServerConnection;
  36 import javax.management.ObjectName;
  37 
  38 import com.sun.management.HotSpotDiagnosticMXBean;
  39 import com.sun.management.UnixOperatingSystemMXBean;
  40 
  41 import sun.management.ManagementFactoryHelper;
  42 import sun.management.Util;
  43 
  44 /**
  45  * This enum class defines the list of platform components
  46  * that provides monitoring and management support.
  47  * Each enum represents one MXBean interface. A MXBean
  48  * instance could implement one or more MXBean interfaces.
  49  *
  50  * For example, com.sun.management.GarbageCollectorMXBean
  51  * extends java.lang.management.GarbageCollectorMXBean
  52  * and there is one set of garbage collection MXBean instances,
  53  * each of which implements both c.s.m. and j.l.m. interfaces.
  54  * There are two separate enums GARBAGE_COLLECTOR
  55  * and SUN_GARBAGE_COLLECTOR so that ManagementFactory.getPlatformMXBeans(Class)
  56  * will return the list of MXBeans of the specified type.
  57  *
  58  * To add a new MXBean interface for the Java platform,
  59  * add a new enum constant and implement the MXBeanFetcher.
  60  */
  61 enum PlatformComponent {
  62 
  63     /**
  64      * Class loading system of the Java virtual machine.
  65      */
  66     CLASS_LOADING(
  67         "java.lang.management.ClassLoadingMXBean",
  68         "java.lang", "ClassLoading", defaultKeyProperties(),
  69         true, // singleton
  70         new MXBeanFetcher<ClassLoadingMXBean>() {
  71             public List<ClassLoadingMXBean> getMXBeans() {
  72                 return Collections.singletonList(ManagementFactoryHelper.getClassLoadingMXBean());
  73             }
  74         }),
  75 
  76     /**
  77      * Compilation system of the Java virtual machine.
  78      */
  79     COMPILATION(
  80         "java.lang.management.CompilationMXBean",
  81         "java.lang", "Compilation", defaultKeyProperties(),
  82         true, // singleton
  83         new MXBeanFetcher<CompilationMXBean>() {
  84             public List<CompilationMXBean> getMXBeans() {
  85                 CompilationMXBean m = ManagementFactoryHelper.getCompilationMXBean();
  86                 if (m == null) {
  87                    return Collections.emptyList();
  88                 } else {
  89                    return Collections.singletonList(m);
  90                 }
  91             }
  92         }),
  93 
  94     /**
  95      * Memory system of the Java virtual machine.
  96      */
  97     MEMORY(
  98         "java.lang.management.MemoryMXBean",
  99         "java.lang", "Memory", defaultKeyProperties(),
 100         true, // singleton
 101         new MXBeanFetcher<MemoryMXBean>() {
 102             public List<MemoryMXBean> getMXBeans() {
 103                 return Collections.singletonList(ManagementFactoryHelper.getMemoryMXBean());
 104             }
 105         }),
 106 
 107     /**
 108      * Garbage Collector in the Java virtual machine.
 109      */
 110     GARBAGE_COLLECTOR(
 111         "java.lang.management.GarbageCollectorMXBean",
 112         "java.lang", "GarbageCollector", keyProperties("name"),
 113         false, // zero or more instances
 114         new MXBeanFetcher<GarbageCollectorMXBean>() {
 115             public List<GarbageCollectorMXBean> getMXBeans() {
 116                 return ManagementFactoryHelper.
 117                            getGarbageCollectorMXBeans();
 118             }
 119         }),
 120 
 121     /**
 122      * Memory manager in the Java virtual machine.
 123      */
 124     MEMORY_MANAGER(
 125         "java.lang.management.MemoryManagerMXBean",
 126         "java.lang", "MemoryManager", keyProperties("name"),
 127         false, // zero or more instances
 128         new MXBeanFetcher<MemoryManagerMXBean>() {
 129             public List<MemoryManagerMXBean> getMXBeans() {
 130                 return ManagementFactoryHelper.getMemoryManagerMXBeans();
 131             }
 132         },
 133         GARBAGE_COLLECTOR),
 134 
 135     /**
 136      * Memory pool in the Java virtual machine.
 137      */
 138     MEMORY_POOL(
 139         "java.lang.management.MemoryPoolMXBean",
 140         "java.lang", "MemoryPool", keyProperties("name"),
 141         false, // zero or more instances
 142         new MXBeanFetcher<MemoryPoolMXBean>() {
 143             public List<MemoryPoolMXBean> getMXBeans() {
 144                 return ManagementFactoryHelper.getMemoryPoolMXBeans();
 145             }
 146         }),
 147 
 148     /**
 149      * Operating system on which the Java virtual machine is running
 150      */
 151     OPERATING_SYSTEM(
 152         "java.lang.management.OperatingSystemMXBean",
 153         "java.lang", "OperatingSystem", defaultKeyProperties(),
 154         true, // singleton
 155         new MXBeanFetcher<OperatingSystemMXBean>() {
 156             public List<OperatingSystemMXBean> getMXBeans() {
 157                 return Collections.singletonList(ManagementFactoryHelper.getOperatingSystemMXBean());
 158             }
 159         }),
 160 
 161     /**
 162      * Runtime system of the Java virtual machine.
 163      */
 164     RUNTIME(
 165         "java.lang.management.RuntimeMXBean",
 166         "java.lang", "Runtime", defaultKeyProperties(),
 167         true, // singleton
 168         new MXBeanFetcher<RuntimeMXBean>() {
 169             public List<RuntimeMXBean> getMXBeans() {
 170                 return Collections.singletonList(ManagementFactoryHelper.getRuntimeMXBean());
 171             }
 172         }),
 173 
 174     /**
 175      * Threading system of the Java virtual machine.
 176      */
 177     THREADING(
 178         "java.lang.management.ThreadMXBean",
 179         "java.lang", "Threading", defaultKeyProperties(),
 180         true, // singleton
 181         new MXBeanFetcher<ThreadMXBean>() {
 182             public List<ThreadMXBean> getMXBeans() {
 183                 return Collections.singletonList(ManagementFactoryHelper.getThreadMXBean());
 184             }
 185         }),
 186 
 187 
 188     /**
 189      * Logging facility.
 190      */
 191     LOGGING(
 192         "java.lang.management.PlatformLoggingMXBean",
 193         "java.util.logging", "Logging", defaultKeyProperties(),
 194         true, // singleton
 195         new MXBeanFetcher<PlatformLoggingMXBean>() {
 196             public List<PlatformLoggingMXBean> getMXBeans() {
 197                 PlatformLoggingMXBean m = ManagementFactoryHelper.getPlatformLoggingMXBean();
 198                 if (m == null) {
 199                    return Collections.emptyList();
 200                 } else {
 201                    return Collections.singletonList(m);
 202                 }
 203             }
 204         }),
 205 
 206     /**
 207      * Buffer pools.
 208      */
 209     BUFFER_POOL(
 210         "java.lang.management.BufferPoolMXBean",
 211         "java.nio", "BufferPool", keyProperties("name"),
 212         false, // zero or more instances
 213         new MXBeanFetcher<BufferPoolMXBean>() {
 214             public List<BufferPoolMXBean> getMXBeans() {
 215                 return ManagementFactoryHelper.getBufferPoolMXBeans();
 216             }
 217         }),
 218 
 219 
 220     // Sun Platform Extension
 221 
 222     /**
 223      * Sun extension garbage collector that performs collections in cycles.
 224      */
 225     SUN_GARBAGE_COLLECTOR(
 226         "com.sun.management.GarbageCollectorMXBean",
 227         "java.lang", "GarbageCollector", keyProperties("name"),
 228         false, // zero or more instances
 229         new MXBeanFetcher<com.sun.management.GarbageCollectorMXBean>() {
 230             public List<com.sun.management.GarbageCollectorMXBean> getMXBeans() {
 231                 return getGcMXBeanList(com.sun.management.GarbageCollectorMXBean.class);
 232             }
 233         }),
 234 
 235     /**
 236      * Sun extension operating system on which the Java virtual machine
 237      * is running.
 238      */
 239     SUN_OPERATING_SYSTEM(
 240         "com.sun.management.OperatingSystemMXBean",
 241         "java.lang", "OperatingSystem", defaultKeyProperties(),
 242         true, // singleton
 243         new MXBeanFetcher<com.sun.management.OperatingSystemMXBean>() {
 244             public List<com.sun.management.OperatingSystemMXBean> getMXBeans() {
 245                 return getOSMXBeanList(com.sun.management.OperatingSystemMXBean.class);
 246             }
 247         }),
 248 
 249     /**
 250      * Unix operating system.
 251      */
 252     SUN_UNIX_OPERATING_SYSTEM(
 253         "com.sun.management.UnixOperatingSystemMXBean",
 254         "java.lang", "OperatingSystem", defaultKeyProperties(),
 255         true, // singleton
 256         new MXBeanFetcher<UnixOperatingSystemMXBean>() {
 257             public List<UnixOperatingSystemMXBean> getMXBeans() {
 258                 return getOSMXBeanList(com.sun.management.UnixOperatingSystemMXBean.class);
 259             }
 260         }),
 261 
 262     /**
 263      * Diagnostic support for the HotSpot Virtual Machine.
 264      */
 265     HOTSPOT_DIAGNOSTIC(
 266         "com.sun.management.HotSpotDiagnosticMXBean",
 267         "com.sun.management", "HotSpotDiagnostic", defaultKeyProperties(),
 268         true, // singleton
 269         new MXBeanFetcher<HotSpotDiagnosticMXBean>() {
 270             public List<HotSpotDiagnosticMXBean> getMXBeans() {
 271                 return Collections.singletonList(ManagementFactoryHelper.getDiagnosticMXBean());
 272             }
 273         });
 274 
 275 
 276     /**
 277      * A task that returns the MXBeans for a component.
 278      */
 279     interface MXBeanFetcher<T extends PlatformManagedObject> {
 280         public List<T> getMXBeans();
 281     }
 282 
 283     /*
 284      * Returns a list of the GC MXBeans of the given type.
 285      */
 286     private static <T extends GarbageCollectorMXBean>
 287             List<T> getGcMXBeanList(Class<T> gcMXBeanIntf) {
 288         List<GarbageCollectorMXBean> list =
 289             ManagementFactoryHelper.getGarbageCollectorMXBeans();
 290         List<T> result = new ArrayList<>(list.size());
 291         for (GarbageCollectorMXBean m : list) {
 292             if (gcMXBeanIntf.isInstance(m)) {
 293                 result.add(gcMXBeanIntf.cast(m));
 294             }
 295         }
 296         return result;
 297     }
 298 
 299     /*
 300      * Returns the OS mxbean instance of the given type.
 301      */
 302     private static <T extends OperatingSystemMXBean>
 303             List<T> getOSMXBeanList(Class<T> osMXBeanIntf) {
 304         OperatingSystemMXBean m =
 305             ManagementFactoryHelper.getOperatingSystemMXBean();
 306         if (osMXBeanIntf.isInstance(m)) {
 307             return Collections.singletonList(osMXBeanIntf.cast(m));
 308         } else {
 309             return Collections.emptyList();
 310         }
 311     }
 312 
 313     private final String mxbeanInterfaceName;
 314     private final String domain;
 315     private final String type;
 316     private final Set<String> keyProperties;
 317     private final MXBeanFetcher<?> fetcher;
 318     private final PlatformComponent[] subComponents;
 319     private final boolean singleton;
 320 
 321     private PlatformComponent(String intfName,
 322                               String domain, String type,
 323                               Set<String> keyProperties,
 324                               boolean singleton,
 325                               MXBeanFetcher<?> fetcher,
 326                               PlatformComponent... subComponents) {
 327         this.mxbeanInterfaceName = intfName;
 328         this.domain = domain;
 329         this.type = type;
 330         this.keyProperties = keyProperties;
 331         this.singleton = singleton;
 332         this.fetcher = fetcher;
 333         this.subComponents = subComponents;
 334     }
 335 
 336     private static Set<String> defaultKeyProps;
 337     private static Set<String> defaultKeyProperties() {
 338         if (defaultKeyProps == null) {
 339             defaultKeyProps = Collections.singleton("type");
 340         }
 341         return defaultKeyProps;
 342     }
 343 
 344     private static Set<String> keyProperties(String... keyNames) {
 345         Set<String> set = new HashSet<>();
 346         set.add("type");
 347         for (String s : keyNames) {
 348             set.add(s);
 349         }
 350         return set;
 351     }
 352 
 353     boolean isSingleton() {
 354         return singleton;
 355     }
 356 
 357     String getMXBeanInterfaceName() {
 358         return mxbeanInterfaceName;
 359     }
 360 
 361     @SuppressWarnings("unchecked")
 362     Class<? extends PlatformManagedObject> getMXBeanInterface() {
 363         try {
 364             // Lazy loading the MXBean interface only when it is needed
 365             return (Class<? extends PlatformManagedObject>)
 366                        Class.forName(mxbeanInterfaceName, false,
 367                                      PlatformManagedObject.class.getClassLoader());
 368         } catch (ClassNotFoundException x) {
 369             throw new AssertionError(x);
 370         }
 371     }
 372 
 373     @SuppressWarnings("unchecked")
 374     <T extends PlatformManagedObject>
 375         List<T> getMXBeans(Class<T> mxbeanInterface)
 376     {
 377         return (List<T>) fetcher.getMXBeans();
 378     }
 379 
 380     <T extends PlatformManagedObject> T getSingletonMXBean(Class<T> mxbeanInterface)
 381     {
 382         if (!singleton)
 383             throw new IllegalArgumentException(mxbeanInterfaceName +
 384                 " can have zero or more than one instances");
 385 
 386         List<T> list = getMXBeans(mxbeanInterface);
 387         assert list.size() == 1;
 388         return list.isEmpty() ? null : list.get(0);
 389     }
 390 
 391     <T extends PlatformManagedObject>
 392             T getSingletonMXBean(MBeanServerConnection mbs, Class<T> mxbeanInterface)
 393         throws java.io.IOException
 394     {
 395         if (!singleton)
 396             throw new IllegalArgumentException(mxbeanInterfaceName +
 397                 " can have zero or more than one instances");
 398 
 399         // ObjectName of a singleton MXBean contains only domain and type
 400         assert keyProperties.size() == 1;
 401         String on = domain + ":type=" + type;
 402         return ManagementFactory.newPlatformMXBeanProxy(mbs,
 403                                                         on,
 404                                                         mxbeanInterface);
 405     }
 406 
 407     <T extends PlatformManagedObject>
 408             List<T> getMXBeans(MBeanServerConnection mbs, Class<T> mxbeanInterface)
 409         throws java.io.IOException
 410     {
 411         List<T> result = new ArrayList<>();
 412         for (ObjectName on : getObjectNames(mbs)) {
 413             result.add(ManagementFactory.
 414                 newPlatformMXBeanProxy(mbs,
 415                                        on.getCanonicalName(),
 416                                        mxbeanInterface)
 417             );
 418         }
 419         return result;
 420     }
 421 
 422     private Set<ObjectName> getObjectNames(MBeanServerConnection mbs)
 423         throws java.io.IOException
 424     {
 425         String domainAndType = domain + ":type=" + type;
 426         if (keyProperties.size() > 1) {
 427             // if there are more than 1 key properties (i.e. other than "type")
 428             domainAndType += ",*";
 429         }
 430         ObjectName on = Util.newObjectName(domainAndType);
 431         Set<ObjectName> set =  mbs.queryNames(on, null);
 432         for (PlatformComponent pc : subComponents) {
 433             set.addAll(pc.getObjectNames(mbs));
 434         }
 435         return set;
 436     }
 437 
 438     // a map from MXBean interface name to PlatformComponent
 439     private static Map<String, PlatformComponent> enumMap;
 440     private static synchronized void ensureInitialized() {
 441         if (enumMap == null) {
 442             enumMap = new HashMap<>();
 443             for (PlatformComponent pc: PlatformComponent.values()) {
 444                 // Use String as the key rather than Class<?> to avoid
 445                 // causing unnecessary class loading of management interface
 446                 enumMap.put(pc.getMXBeanInterfaceName(), pc);
 447             }
 448         }
 449     }
 450 
 451     static boolean isPlatformMXBean(String cn) {
 452         ensureInitialized();
 453         return enumMap.containsKey(cn);
 454     }
 455 
 456     static <T extends PlatformManagedObject>
 457         PlatformComponent getPlatformComponent(Class<T> mxbeanInterface)
 458     {
 459         ensureInitialized();
 460         String cn = mxbeanInterface.getName();
 461         PlatformComponent pc = enumMap.get(cn);
 462         if (pc != null && pc.getMXBeanInterface() == mxbeanInterface)
 463             return pc;
 464         return null;
 465     }
 466 
 467     private static final long serialVersionUID = 6992337162326171013L;
 468 }