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