Path: blob/master/src/java.management/share/classes/sun/management/ManagementFactoryHelper.java
41152 views
/*1* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.management;2627import java.lang.invoke.MethodHandles;28import java.lang.management.*;29import java.lang.reflect.InvocationTargetException;30import java.lang.reflect.Method;31import javax.management.InstanceAlreadyExistsException;32import javax.management.InstanceNotFoundException;33import javax.management.MBeanServer;34import javax.management.MBeanRegistrationException;35import javax.management.NotCompliantMBeanException;36import javax.management.ObjectName;37import javax.management.RuntimeOperationsException;38import java.security.AccessController;39import java.security.PrivilegedActionException;40import java.security.PrivilegedExceptionAction;4142import jdk.internal.misc.VM;43import jdk.internal.misc.VM.BufferPool;4445import java.util.ArrayList;46import java.util.List;4748import java.lang.reflect.UndeclaredThrowableException;49import java.security.PrivilegedAction;50import java.util.Arrays;51import java.util.Collections;52import java.util.HashMap;53import java.util.Map;54import java.util.Optional;55import java.util.stream.Collectors;5657/**58* ManagementFactoryHelper provides static factory methods to create59* instances of the management interface.60*/61public class ManagementFactoryHelper {62static {63// make sure that the management lib is loaded within64// java.lang.management.ManagementFactory65try {66MethodHandles.lookup().ensureInitialized(ManagementFactory.class);67} catch (IllegalAccessException e) {}68}6970private static final VMManagement jvm = new VMManagementImpl();7172private ManagementFactoryHelper() {};7374public static VMManagement getVMManagement() {75return jvm;76}7778static final String LOGGING_MXBEAN_NAME = "java.util.logging:type=Logging";79private static ClassLoadingImpl classMBean = null;80private static MemoryImpl memoryMBean = null;81private static ThreadImpl threadMBean = null;82private static RuntimeImpl runtimeMBean = null;83private static CompilationImpl compileMBean = null;84private static BaseOperatingSystemImpl osMBean = null;8586public static synchronized ClassLoadingMXBean getClassLoadingMXBean() {87if (classMBean == null) {88classMBean = new ClassLoadingImpl(jvm);89}90return classMBean;91}9293public static synchronized MemoryMXBean getMemoryMXBean() {94if (memoryMBean == null) {95memoryMBean = new MemoryImpl(jvm);96}97return memoryMBean;98}99100public static synchronized ThreadMXBean getThreadMXBean() {101if (threadMBean == null) {102threadMBean = new ThreadImpl(jvm);103}104return threadMBean;105}106107public static synchronized RuntimeMXBean getRuntimeMXBean() {108if (runtimeMBean == null) {109runtimeMBean = new RuntimeImpl(jvm);110}111return runtimeMBean;112}113114public static synchronized CompilationMXBean getCompilationMXBean() {115if (compileMBean == null && jvm.getCompilerName() != null) {116compileMBean = new CompilationImpl(jvm);117}118return compileMBean;119}120121public static synchronized OperatingSystemMXBean getOperatingSystemMXBean() {122if (osMBean == null) {123osMBean = new BaseOperatingSystemImpl(jvm);124}125return osMBean;126}127128public static List<MemoryPoolMXBean> getMemoryPoolMXBeans() {129MemoryPoolMXBean[] pools = MemoryImpl.getMemoryPools();130List<MemoryPoolMXBean> list = new ArrayList<>(pools.length);131for (MemoryPoolMXBean p : pools) {132list.add(p);133}134return list;135}136137public static List<MemoryManagerMXBean> getMemoryManagerMXBeans() {138MemoryManagerMXBean[] mgrs = MemoryImpl.getMemoryManagers();139List<MemoryManagerMXBean> result = new ArrayList<>(mgrs.length);140for (MemoryManagerMXBean m : mgrs) {141result.add(m);142}143return result;144}145146public static List<GarbageCollectorMXBean> getGarbageCollectorMXBeans() {147MemoryManagerMXBean[] mgrs = MemoryImpl.getMemoryManagers();148List<GarbageCollectorMXBean> result = new ArrayList<>(mgrs.length);149for (MemoryManagerMXBean m : mgrs) {150if (GarbageCollectorMXBean.class.isInstance(m)) {151result.add(GarbageCollectorMXBean.class.cast(m));152}153}154return result;155}156157public static PlatformLoggingMXBean getPlatformLoggingMXBean() {158if (LoggingMXBeanAccess.isAvailable()) {159return PlatformLoggingImpl.MBEAN;160} else {161return null;162}163}164165public static boolean isPlatformLoggingMXBeanAvailable() {166return LoggingMXBeanAccess.isAvailable();167}168169/**170* Returns an array of the name of all memory pools. The order of the memory pools is171* significant and maintained in the VM.172*/173public static String[] getAllMemoryPoolNames() {174return Arrays.stream(MemoryImpl.getMemoryPools())175.map(MemoryPoolMXBean::getName)176.toArray(String[]::new);177}178179// The LoggingMXBeanAccess class uses reflection to determine180// whether java.util.logging is present, and load the actual LoggingMXBean181// implementation.182//183static final class LoggingMXBeanAccess {184185static final String LOG_MANAGER_CLASS_NAME = "java.util.logging.LogManager";186static final String LOGGING_MXBEAN_CLASS_NAME = "java.util.logging.LoggingMXBean";187static final Class<?> LOG_MANAGER_CLASS = loadLoggingClass(LOG_MANAGER_CLASS_NAME);188189static boolean isAvailable() {190return LOG_MANAGER_CLASS != null;191}192193@SuppressWarnings("removal")194private static Class<?> loadLoggingClass(String className) {195return AccessController.doPrivileged(new PrivilegedAction<>() {196@Override197public Class<?> run() {198Optional<Module> logging = ModuleLayer.boot().findModule("java.logging");199if (logging.isPresent()) {200return Class.forName(logging.get(), className);201}202return null;203}204});205}206207private Map<String, Method> initMethodMap(Object impl) {208if (impl == null) {209return Collections.emptyMap();210}211Class<?> intfClass = loadLoggingClass(LOGGING_MXBEAN_CLASS_NAME);212final Map<String, Method> methodsMap = new HashMap<>();213for (Method m : intfClass.getMethods()) {214try {215// Sanity checking: all public methods present in216// java.util.logging.LoggingMXBean should217// also be in PlatformLoggingMXBean218Method specMethod = PlatformLoggingMXBean.class219.getMethod(m.getName(), m.getParameterTypes());220if (specMethod.getReturnType().isAssignableFrom(m.getReturnType())) {221if (methodsMap.putIfAbsent(m.getName(), m) != null) {222throw new RuntimeException("unexpected polymorphic method: "223+ m.getName());224}225}226} catch (NoSuchMethodException x) {227// All methods in java.util.logging.LoggingMXBean should228// also be in PlatformLoggingMXBean229throw new InternalError(x);230}231}232return Collections.unmodifiableMap(methodsMap);233}234235private static Object getMXBeanImplementation() {236if (!isAvailable()) {237// should not happen238throw new NoClassDefFoundError(LOG_MANAGER_CLASS_NAME);239}240try {241final Method m = LOG_MANAGER_CLASS.getMethod("getLoggingMXBean");242return m.invoke(null);243} catch (NoSuchMethodException244| IllegalAccessException245| InvocationTargetException x) {246throw new ExceptionInInitializerError(x);247}248}249250// The implementation object, which will be invoked through251// reflection. The implementation does not need to implement252// PlatformLoggingMXBean, but must declare the same methods253// with same signatures, and they must be public, with one254// exception:255// getObjectName will not be called on the implementation object,256// so the implementation object does not need to declare such257// a method.258final Object impl = getMXBeanImplementation();259final Map<String, Method> methods = initMethodMap(impl);260261LoggingMXBeanAccess() {262}263264<T> T invoke(String methodName, Object... args) {265Method m = methods.get(methodName);266if (m == null) {267throw new UnsupportedOperationException(methodName);268}269try {270@SuppressWarnings("unchecked")271T result = (T) m.invoke(impl, args);272return result;273} catch (IllegalAccessException ex) {274throw new UnsupportedOperationException(ex);275} catch (InvocationTargetException ex) {276throw unwrap(ex);277}278}279280private static RuntimeException unwrap(InvocationTargetException x) {281Throwable t = x.getCause();282if (t instanceof RuntimeException) {283return (RuntimeException)t;284}285if (t instanceof Error) {286throw (Error)t;287}288return new UndeclaredThrowableException(t == null ? x : t);289}290291292}293294static final class PlatformLoggingImpl implements PlatformLoggingMXBean {295296private final LoggingMXBeanAccess loggingAccess;297private PlatformLoggingImpl(LoggingMXBeanAccess loggingAccess) {298this.loggingAccess = loggingAccess;299}300301private volatile ObjectName objname; // created lazily302@Override303public ObjectName getObjectName() {304ObjectName result = objname;305if (result == null) {306synchronized (this) {307result = objname;308if (result == null) {309result = Util.newObjectName(LOGGING_MXBEAN_NAME);310objname = result;311}312}313}314return result;315}316317@Override318public java.util.List<String> getLoggerNames() {319return loggingAccess.invoke("getLoggerNames");320}321322@Override323public String getLoggerLevel(String loggerName) {324return loggingAccess.invoke("getLoggerLevel", loggerName);325}326327@Override328public void setLoggerLevel(String loggerName, String levelName) {329loggingAccess.invoke("setLoggerLevel", loggerName, levelName);330}331332@Override333public String getParentLoggerName(String loggerName) {334return loggingAccess.invoke("getParentLoggerName", loggerName);335}336337private static PlatformLoggingImpl getInstance() {338return new PlatformLoggingImpl(new LoggingMXBeanAccess());339}340341static final PlatformLoggingMXBean MBEAN = getInstance();342}343344private static volatile List<BufferPoolMXBean> bufferPools;345public static List<BufferPoolMXBean> getBufferPoolMXBeans() {346if (bufferPools == null) {347synchronized (ManagementFactoryHelper.class) {348if (bufferPools == null) {349bufferPools = VM.getBufferPools().stream()350.map(ManagementFactoryHelper::createBufferPoolMXBean)351.collect(Collectors.toList());352}353}354}355return bufferPools;356}357358private static final String BUFFER_POOL_MXBEAN_NAME = "java.nio:type=BufferPool";359360/**361* Creates management interface for the given buffer pool.362*/363private static BufferPoolMXBean364createBufferPoolMXBean(final BufferPool pool)365{366return new BufferPoolMXBean() {367private volatile ObjectName objname; // created lazily368@Override369public ObjectName getObjectName() {370ObjectName result = objname;371if (result == null) {372synchronized (this) {373result = objname;374if (result == null) {375result = Util.newObjectName(BUFFER_POOL_MXBEAN_NAME +376",name=" + pool.getName());377objname = result;378}379}380}381return result;382}383@Override384public String getName() {385return pool.getName();386}387@Override388public long getCount() {389return pool.getCount();390}391@Override392public long getTotalCapacity() {393return pool.getTotalCapacity();394}395@Override396public long getMemoryUsed() {397return pool.getMemoryUsed();398}399};400}401402private static HotspotRuntime hsRuntimeMBean = null;403private static HotspotClassLoading hsClassMBean = null;404private static HotspotThread hsThreadMBean = null;405private static HotspotCompilation hsCompileMBean = null;406private static HotspotMemory hsMemoryMBean = null;407408/**409* This method is for testing only.410*/411public static synchronized HotspotRuntimeMBean getHotspotRuntimeMBean() {412if (hsRuntimeMBean == null) {413hsRuntimeMBean = new HotspotRuntime(jvm);414}415return hsRuntimeMBean;416}417418/**419* This method is for testing only.420*/421public static synchronized HotspotClassLoadingMBean getHotspotClassLoadingMBean() {422if (hsClassMBean == null) {423hsClassMBean = new HotspotClassLoading(jvm);424}425return hsClassMBean;426}427428/**429* This method is for testing only.430*/431public static synchronized HotspotThreadMBean getHotspotThreadMBean() {432if (hsThreadMBean == null) {433hsThreadMBean = new HotspotThread(jvm);434}435return hsThreadMBean;436}437438/**439* This method is for testing only.440*/441public static synchronized HotspotMemoryMBean getHotspotMemoryMBean() {442if (hsMemoryMBean == null) {443hsMemoryMBean = new HotspotMemory(jvm);444}445return hsMemoryMBean;446}447448/**449* This method is for testing only.450*/451public static synchronized HotspotCompilationMBean getHotspotCompilationMBean() {452if (hsCompileMBean == null) {453hsCompileMBean = new HotspotCompilation(jvm);454}455return hsCompileMBean;456}457458/**459* Registers a given MBean if not registered in the MBeanServer;460* otherwise, just return.461*/462@SuppressWarnings("removal")463private static void addMBean(MBeanServer mbs, Object mbean, String mbeanName) {464try {465final ObjectName objName = Util.newObjectName(mbeanName);466467// inner class requires these fields to be final468final MBeanServer mbs0 = mbs;469final Object mbean0 = mbean;470AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {471public Void run() throws MBeanRegistrationException,472NotCompliantMBeanException {473try {474mbs0.registerMBean(mbean0, objName);475return null;476} catch (InstanceAlreadyExistsException e) {477// if an instance with the object name exists in478// the MBeanServer ignore the exception479}480return null;481}482});483} catch (PrivilegedActionException e) {484throw Util.newException(e.getException());485}486}487488private static final String HOTSPOT_CLASS_LOADING_MBEAN_NAME =489"sun.management:type=HotspotClassLoading";490491private static final String HOTSPOT_COMPILATION_MBEAN_NAME =492"sun.management:type=HotspotCompilation";493494private static final String HOTSPOT_MEMORY_MBEAN_NAME =495"sun.management:type=HotspotMemory";496497private static final String HOTSPOT_RUNTIME_MBEAN_NAME =498"sun.management:type=HotspotRuntime";499500private static final String HOTSPOT_THREAD_MBEAN_NAME =501"sun.management:type=HotspotThreading";502503static void registerInternalMBeans(MBeanServer mbs) {504// register all internal MBeans if not registered505// No exception is thrown if a MBean with that object name506// already registered507addMBean(mbs, getHotspotClassLoadingMBean(),508HOTSPOT_CLASS_LOADING_MBEAN_NAME);509addMBean(mbs, getHotspotMemoryMBean(),510HOTSPOT_MEMORY_MBEAN_NAME);511addMBean(mbs, getHotspotRuntimeMBean(),512HOTSPOT_RUNTIME_MBEAN_NAME);513addMBean(mbs, getHotspotThreadMBean(),514HOTSPOT_THREAD_MBEAN_NAME);515516// CompilationMBean may not exist517if (getCompilationMXBean() != null) {518addMBean(mbs, getHotspotCompilationMBean(),519HOTSPOT_COMPILATION_MBEAN_NAME);520}521}522523@SuppressWarnings("removal")524private static void unregisterMBean(MBeanServer mbs, String mbeanName) {525try {526final ObjectName objName = Util.newObjectName(mbeanName);527528// inner class requires these fields to be final529final MBeanServer mbs0 = mbs;530AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {531public Void run() throws MBeanRegistrationException,532RuntimeOperationsException {533try {534mbs0.unregisterMBean(objName);535} catch (InstanceNotFoundException e) {536// ignore exception if not found537}538return null;539}540});541} catch (PrivilegedActionException e) {542throw Util.newException(e.getException());543}544}545546static void unregisterInternalMBeans(MBeanServer mbs) {547// unregister all internal MBeans548unregisterMBean(mbs, HOTSPOT_CLASS_LOADING_MBEAN_NAME);549unregisterMBean(mbs, HOTSPOT_MEMORY_MBEAN_NAME);550unregisterMBean(mbs, HOTSPOT_RUNTIME_MBEAN_NAME);551unregisterMBean(mbs, HOTSPOT_THREAD_MBEAN_NAME);552553// CompilationMBean may not exist554if (getCompilationMXBean() != null) {555unregisterMBean(mbs, HOTSPOT_COMPILATION_MBEAN_NAME);556}557}558559public static boolean isThreadSuspended(int state) {560return ((state & JMM_THREAD_STATE_FLAG_SUSPENDED) != 0);561}562563public static boolean isThreadRunningNative(int state) {564return ((state & JMM_THREAD_STATE_FLAG_NATIVE) != 0);565}566567public static Thread.State toThreadState(int state) {568// suspended and native bits may be set in state569int threadStatus = state & ~JMM_THREAD_STATE_FLAG_MASK;570return jdk.internal.misc.VM.toThreadState(threadStatus);571}572573// These values are defined in jmm.h574private static final int JMM_THREAD_STATE_FLAG_MASK = 0xFFF00000;575private static final int JMM_THREAD_STATE_FLAG_SUSPENDED = 0x00100000;576private static final int JMM_THREAD_STATE_FLAG_NATIVE = 0x00400000;577578// Invoked by the VM579private static MemoryPoolMXBean createMemoryPool580(String name, boolean isHeap, long uThreshold, long gcThreshold) {581return new MemoryPoolImpl(name, isHeap, uThreshold, gcThreshold);582}583584private static MemoryManagerMXBean createMemoryManager(String name) {585return new MemoryManagerImpl(name);586}587588private static GarbageCollectorMXBean589createGarbageCollector(String name, String type) {590591// ignore type parameter which is for future extension592return new GarbageCollectorImpl(name);593}594}595596597