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