1 /*
   2  * Copyright (c) 2003, 2019, 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 sun.management;
  27 
  28 import java.lang.management.*;
  29 
  30 import javax.management.DynamicMBean;
  31 import javax.management.InstanceAlreadyExistsException;
  32 import javax.management.InstanceNotFoundException;
  33 import javax.management.MBeanServer;
  34 import javax.management.MBeanRegistrationException;
  35 import javax.management.NotCompliantMBeanException;
  36 import javax.management.ObjectName;
  37 import javax.management.RuntimeOperationsException;
  38 import java.security.AccessController;
  39 import java.security.PrivilegedActionException;
  40 import java.security.PrivilegedExceptionAction;
  41 
  42 import sun.util.logging.LoggingSupport;
  43 
  44 import java.util.ArrayList;
  45 import java.util.Collections;
  46 import java.util.HashMap;
  47 import java.util.List;
  48 import com.sun.management.DiagnosticCommandMBean;
  49 import com.sun.management.HotSpotDiagnosticMXBean;
  50 
  51 import jdk.management.jfr.FlightRecorderMXBean;
  52 import jdk.management.jfr.FlightRecorderMXBeanImpl;
  53 
  54 import static java.lang.management.ManagementFactory.*;
  55 
  56 /**
  57  * ManagementFactoryHelper provides static factory methods to create
  58  * instances of the management interface.
  59  */
  60 public class ManagementFactoryHelper {
  61     private ManagementFactoryHelper() {};
  62 
  63     private static VMManagement jvm;
  64 
  65     private static ClassLoadingImpl    classMBean = null;
  66     private static MemoryImpl          memoryMBean = null;
  67     private static ThreadImpl          threadMBean = null;
  68     private static RuntimeImpl         runtimeMBean = null;
  69     private static CompilationImpl     compileMBean = null;
  70     private static OperatingSystemImpl osMBean = null;
  71     private static FlightRecorderMXBeanImpl  flightRecorderMBean = null;
  72 
  73     public static synchronized ClassLoadingMXBean getClassLoadingMXBean() {
  74         if (classMBean == null) {
  75             classMBean = new ClassLoadingImpl(jvm);
  76         }
  77         return classMBean;
  78     }
  79 
  80     public static synchronized MemoryMXBean getMemoryMXBean() {
  81         if (memoryMBean == null) {
  82             memoryMBean = new MemoryImpl(jvm);
  83         }
  84         return memoryMBean;
  85     }
  86 
  87     public static synchronized ThreadMXBean getThreadMXBean() {
  88         if (threadMBean == null) {
  89             threadMBean = new ThreadImpl(jvm);
  90         }
  91         return threadMBean;
  92     }
  93 
  94     public static synchronized RuntimeMXBean getRuntimeMXBean() {
  95         if (runtimeMBean == null) {
  96             runtimeMBean = new RuntimeImpl(jvm);
  97         }
  98         return runtimeMBean;
  99     }
 100 
 101     public static synchronized CompilationMXBean getCompilationMXBean() {
 102         if (compileMBean == null && jvm.getCompilerName() != null) {
 103             compileMBean = new CompilationImpl(jvm);
 104         }
 105         return compileMBean;
 106     }
 107 
 108     public static synchronized OperatingSystemMXBean getOperatingSystemMXBean() {
 109         if (osMBean == null) {
 110             osMBean = new OperatingSystemImpl(jvm);
 111         }
 112         return osMBean;
 113     }
 114 
 115     public static synchronized FlightRecorderMXBean getFlightRecorderMXBean() {
 116         if (flightRecorderMBean == null) {
 117             flightRecorderMBean = new FlightRecorderMXBeanImpl();
 118         }
 119         return flightRecorderMBean;
 120     }
 121 
 122     public static List<MemoryPoolMXBean> getMemoryPoolMXBeans() {
 123         MemoryPoolMXBean[] pools = MemoryImpl.getMemoryPools();
 124         List<MemoryPoolMXBean> list = new ArrayList<>(pools.length);
 125         for (MemoryPoolMXBean p : pools) {
 126             list.add(p);
 127         }
 128         return list;
 129     }
 130 
 131     public static List<MemoryManagerMXBean> getMemoryManagerMXBeans() {
 132         MemoryManagerMXBean[]  mgrs = MemoryImpl.getMemoryManagers();
 133         List<MemoryManagerMXBean> result = new ArrayList<>(mgrs.length);
 134         for (MemoryManagerMXBean m : mgrs) {
 135             result.add(m);
 136         }
 137         return result;
 138     }
 139 
 140     public static List<GarbageCollectorMXBean> getGarbageCollectorMXBeans() {
 141         MemoryManagerMXBean[]  mgrs = MemoryImpl.getMemoryManagers();
 142         List<GarbageCollectorMXBean> result = new ArrayList<>(mgrs.length);
 143         for (MemoryManagerMXBean m : mgrs) {
 144             if (GarbageCollectorMXBean.class.isInstance(m)) {
 145                  result.add(GarbageCollectorMXBean.class.cast(m));
 146             }
 147         }
 148         return result;
 149     }
 150 
 151     public static PlatformLoggingMXBean getPlatformLoggingMXBean() {
 152         if (LoggingSupport.isAvailable()) {
 153             return PlatformLoggingImpl.instance;
 154         } else {
 155             return null;
 156         }
 157     }
 158 
 159     /**
 160      * The logging MXBean object is an instance of
 161      * PlatformLoggingMXBean and java.util.logging.LoggingMXBean
 162      * but it can't directly implement two MXBean interfaces
 163      * as a compliant MXBean implements exactly one MXBean interface,
 164      * or if it implements one interface that is a subinterface of
 165      * all the others; otherwise, it is a non-compliant MXBean
 166      * and MBeanServer will throw NotCompliantMBeanException.
 167      * See the Definition of an MXBean section in javax.management.MXBean spec.
 168      *
 169      * To create a compliant logging MXBean, define a LoggingMXBean interface
 170      * that extend PlatformLoggingMXBean and j.u.l.LoggingMXBean
 171     */
 172     public interface LoggingMXBean
 173         extends PlatformLoggingMXBean, java.util.logging.LoggingMXBean {
 174     }
 175 
 176     static class PlatformLoggingImpl implements LoggingMXBean
 177     {
 178         final static PlatformLoggingMXBean instance = new PlatformLoggingImpl();
 179         final static String LOGGING_MXBEAN_NAME = "java.util.logging:type=Logging";
 180 
 181         private volatile ObjectName objname;  // created lazily
 182         @Override
 183         public ObjectName getObjectName() {
 184             ObjectName result = objname;
 185             if (result == null) {
 186                 synchronized (this) {
 187                     result = objname;
 188                     if (result == null) {
 189                         result = Util.newObjectName(LOGGING_MXBEAN_NAME);
 190                         objname = result;
 191                     }
 192                 }
 193             }
 194             return result;
 195         }
 196 
 197         @Override
 198         public java.util.List<String> getLoggerNames() {
 199             return LoggingSupport.getLoggerNames();
 200         }
 201 
 202         @Override
 203         public String getLoggerLevel(String loggerName) {
 204             return LoggingSupport.getLoggerLevel(loggerName);
 205         }
 206 
 207         @Override
 208         public void setLoggerLevel(String loggerName, String levelName) {
 209             LoggingSupport.setLoggerLevel(loggerName, levelName);
 210         }
 211 
 212         @Override
 213         public String getParentLoggerName(String loggerName) {
 214             return LoggingSupport.getParentLoggerName(loggerName);
 215         }
 216     }
 217 
 218     private static List<BufferPoolMXBean> bufferPools = null;
 219     public static synchronized List<BufferPoolMXBean> getBufferPoolMXBeans() {
 220         if (bufferPools == null) {
 221             bufferPools = new ArrayList<>(2);
 222             bufferPools.add(createBufferPoolMXBean(sun.misc.SharedSecrets.getJavaNioAccess()
 223                 .getDirectBufferPool()));
 224             bufferPools.add(createBufferPoolMXBean(sun.nio.ch.FileChannelImpl
 225                 .getMappedBufferPool()));
 226         }
 227         return bufferPools;
 228     }
 229 
 230     private final static String BUFFER_POOL_MXBEAN_NAME = "java.nio:type=BufferPool";
 231 
 232     /**
 233      * Creates management interface for the given buffer pool.
 234      */
 235     private static BufferPoolMXBean
 236         createBufferPoolMXBean(final sun.misc.JavaNioAccess.BufferPool pool)
 237     {
 238         return new BufferPoolMXBean() {
 239             private volatile ObjectName objname;  // created lazily
 240             @Override
 241             public ObjectName getObjectName() {
 242                 ObjectName result = objname;
 243                 if (result == null) {
 244                     synchronized (this) {
 245                         result = objname;
 246                         if (result == null) {
 247                             result = Util.newObjectName(BUFFER_POOL_MXBEAN_NAME +
 248                                 ",name=" + pool.getName());
 249                             objname = result;
 250                         }
 251                     }
 252                 }
 253                 return result;
 254             }
 255             @Override
 256             public String getName() {
 257                 return pool.getName();
 258             }
 259             @Override
 260             public long getCount() {
 261                 return pool.getCount();
 262             }
 263             @Override
 264             public long getTotalCapacity() {
 265                 return pool.getTotalCapacity();
 266             }
 267             @Override
 268             public long getMemoryUsed() {
 269                 return pool.getMemoryUsed();
 270             }
 271         };
 272     }
 273 
 274     private static HotSpotDiagnostic hsDiagMBean = null;
 275     private static HotspotRuntime hsRuntimeMBean = null;
 276     private static HotspotClassLoading hsClassMBean = null;
 277     private static HotspotThread hsThreadMBean = null;
 278     private static HotspotCompilation hsCompileMBean = null;
 279     private static HotspotMemory hsMemoryMBean = null;
 280     private static DiagnosticCommandImpl hsDiagCommandMBean = null;
 281 
 282     public static synchronized HotSpotDiagnosticMXBean getDiagnosticMXBean() {
 283         if (hsDiagMBean == null) {
 284             hsDiagMBean = new HotSpotDiagnostic();
 285         }
 286         return hsDiagMBean;
 287     }
 288 
 289     /**
 290      * This method is for testing only.
 291      */
 292     public static synchronized HotspotRuntimeMBean getHotspotRuntimeMBean() {
 293         if (hsRuntimeMBean == null) {
 294             hsRuntimeMBean = new HotspotRuntime(jvm);
 295         }
 296         return hsRuntimeMBean;
 297     }
 298 
 299     /**
 300      * This method is for testing only.
 301      */
 302     public static synchronized HotspotClassLoadingMBean getHotspotClassLoadingMBean() {
 303         if (hsClassMBean == null) {
 304             hsClassMBean = new HotspotClassLoading(jvm);
 305         }
 306         return hsClassMBean;
 307     }
 308 
 309     /**
 310      * This method is for testing only.
 311      */
 312     public static synchronized HotspotThreadMBean getHotspotThreadMBean() {
 313         if (hsThreadMBean == null) {
 314             hsThreadMBean = new HotspotThread(jvm);
 315         }
 316         return hsThreadMBean;
 317     }
 318 
 319     /**
 320      * This method is for testing only.
 321      */
 322     public static synchronized HotspotMemoryMBean getHotspotMemoryMBean() {
 323         if (hsMemoryMBean == null) {
 324             hsMemoryMBean = new HotspotMemory(jvm);
 325         }
 326         return hsMemoryMBean;
 327     }
 328 
 329     public static synchronized DiagnosticCommandMBean getDiagnosticCommandMBean() {
 330         // Remote Diagnostic Commands may not be supported
 331         if (hsDiagCommandMBean == null && jvm.isRemoteDiagnosticCommandsSupported()) {
 332             hsDiagCommandMBean = new DiagnosticCommandImpl(jvm);
 333         }
 334         return hsDiagCommandMBean;
 335     }
 336 
 337     /**
 338      * This method is for testing only.
 339      */
 340     public static synchronized HotspotCompilationMBean getHotspotCompilationMBean() {
 341         if (hsCompileMBean == null) {
 342             hsCompileMBean = new HotspotCompilation(jvm);
 343         }
 344         return hsCompileMBean;
 345     }
 346 
 347     /**
 348      * Registers a given MBean if not registered in the MBeanServer;
 349      * otherwise, just return.
 350      */
 351     private static void addMBean(MBeanServer mbs, Object mbean, String mbeanName) {
 352         try {
 353             final ObjectName objName = Util.newObjectName(mbeanName);
 354 
 355             // inner class requires these fields to be final
 356             final MBeanServer mbs0 = mbs;
 357             final Object mbean0 = mbean;
 358             AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
 359                 public Void run() throws MBeanRegistrationException,
 360                                          NotCompliantMBeanException {
 361                     try {
 362                         mbs0.registerMBean(mbean0, objName);
 363                         return null;
 364                     } catch (InstanceAlreadyExistsException e) {
 365                         // if an instance with the object name exists in
 366                         // the MBeanServer ignore the exception
 367                     }
 368                     return null;
 369                 }
 370             });
 371         } catch (PrivilegedActionException e) {
 372             throw Util.newException(e.getException());
 373         }
 374     }
 375 
 376     private final static String HOTSPOT_CLASS_LOADING_MBEAN_NAME =
 377         "sun.management:type=HotspotClassLoading";
 378 
 379     private final static String HOTSPOT_COMPILATION_MBEAN_NAME =
 380         "sun.management:type=HotspotCompilation";
 381 
 382     private final static String HOTSPOT_MEMORY_MBEAN_NAME =
 383         "sun.management:type=HotspotMemory";
 384 
 385     private static final String HOTSPOT_RUNTIME_MBEAN_NAME =
 386         "sun.management:type=HotspotRuntime";
 387 
 388     private final static String HOTSPOT_THREAD_MBEAN_NAME =
 389         "sun.management:type=HotspotThreading";
 390 
 391     final static String HOTSPOT_DIAGNOSTIC_COMMAND_MBEAN_NAME =
 392         "com.sun.management:type=DiagnosticCommand";
 393 
 394     public static HashMap<ObjectName, DynamicMBean> getPlatformDynamicMBeans() {
 395         HashMap<ObjectName, DynamicMBean> map = new HashMap<>();
 396         DiagnosticCommandMBean diagMBean = getDiagnosticCommandMBean();
 397         if (diagMBean != null) {
 398             map.put(Util.newObjectName(HOTSPOT_DIAGNOSTIC_COMMAND_MBEAN_NAME), diagMBean);
 399         }
 400         return map;
 401     }
 402 
 403     static void registerInternalMBeans(MBeanServer mbs) {
 404         // register all internal MBeans if not registered
 405         // No exception is thrown if a MBean with that object name
 406         // already registered
 407         addMBean(mbs, getHotspotClassLoadingMBean(),
 408             HOTSPOT_CLASS_LOADING_MBEAN_NAME);
 409         addMBean(mbs, getHotspotMemoryMBean(),
 410             HOTSPOT_MEMORY_MBEAN_NAME);
 411         addMBean(mbs, getHotspotRuntimeMBean(),
 412             HOTSPOT_RUNTIME_MBEAN_NAME);
 413         addMBean(mbs, getHotspotThreadMBean(),
 414             HOTSPOT_THREAD_MBEAN_NAME);
 415 
 416         // CompilationMBean may not exist
 417         if (getCompilationMXBean() != null) {
 418             addMBean(mbs, getHotspotCompilationMBean(),
 419                 HOTSPOT_COMPILATION_MBEAN_NAME);
 420         }
 421     }
 422 
 423     private static void unregisterMBean(MBeanServer mbs, String mbeanName) {
 424         try {
 425             final ObjectName objName = Util.newObjectName(mbeanName);
 426 
 427             // inner class requires these fields to be final
 428             final MBeanServer mbs0 = mbs;
 429             AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
 430                 public Void run() throws MBeanRegistrationException,
 431                                            RuntimeOperationsException  {
 432                     try {
 433                         mbs0.unregisterMBean(objName);
 434                     } catch (InstanceNotFoundException e) {
 435                         // ignore exception if not found
 436                     }
 437                     return null;
 438                 }
 439             });
 440         } catch (PrivilegedActionException e) {
 441             throw Util.newException(e.getException());
 442         }
 443     }
 444 
 445     static void unregisterInternalMBeans(MBeanServer mbs) {
 446         // unregister all internal MBeans
 447         unregisterMBean(mbs, HOTSPOT_CLASS_LOADING_MBEAN_NAME);
 448         unregisterMBean(mbs, HOTSPOT_MEMORY_MBEAN_NAME);
 449         unregisterMBean(mbs, HOTSPOT_RUNTIME_MBEAN_NAME);
 450         unregisterMBean(mbs, HOTSPOT_THREAD_MBEAN_NAME);
 451 
 452         // CompilationMBean may not exist
 453         if (getCompilationMXBean() != null) {
 454             unregisterMBean(mbs, HOTSPOT_COMPILATION_MBEAN_NAME);
 455         }
 456     }
 457 
 458     static {
 459         AccessController.doPrivileged(
 460             new java.security.PrivilegedAction<Void>() {
 461                 public Void run() {
 462                     System.loadLibrary("management");
 463                     return null;
 464                 }
 465             });
 466         jvm = new VMManagementImpl();
 467     }
 468 
 469     public static boolean isThreadSuspended(int state) {
 470         return ((state & JMM_THREAD_STATE_FLAG_SUSPENDED) != 0);
 471     }
 472 
 473     public static boolean isThreadRunningNative(int state) {
 474         return ((state & JMM_THREAD_STATE_FLAG_NATIVE) != 0);
 475     }
 476 
 477     public static Thread.State toThreadState(int state) {
 478         // suspended and native bits may be set in state
 479         int threadStatus = state & ~JMM_THREAD_STATE_FLAG_MASK;
 480         return sun.misc.VM.toThreadState(threadStatus);
 481     }
 482 
 483     // These values are defined in jmm.h
 484     private static final int JMM_THREAD_STATE_FLAG_MASK = 0xFFF00000;
 485     private static final int JMM_THREAD_STATE_FLAG_SUSPENDED = 0x00100000;
 486     private static final int JMM_THREAD_STATE_FLAG_NATIVE = 0x00400000;
 487 
 488 }