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 }