--- a/jdk/src/java.management/share/classes/java/lang/management/ManagementFactory.java Thu Feb 05 11:42:39 2015 +0800
+++ b/jdk/src/java.management/share/classes/java/lang/management/ManagementFactory.java Thu Feb 05 12:13:45 2015 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -24,35 +24,40 @@
*/
package java.lang.management;
+import java.io.FilePermission;
+import java.io.IOException;
import javax.management.DynamicMBean;
import javax.management.MBeanServer;
import javax.management.MBeanServerConnection;
import javax.management.MBeanServerFactory;
import javax.management.MBeanServerPermission;
import javax.management.NotificationEmitter;
-import javax.management.ObjectInstance;
import javax.management.ObjectName;
-import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import javax.management.MalformedObjectNameException;
-import javax.management.MBeanRegistrationException;
-import javax.management.NotCompliantMBeanException;
import javax.management.StandardEmitterMBean;
import javax.management.StandardMBean;
import java.util.Collections;
import java.util.List;
import java.util.Set;
-import java.util.HashMap;
-import java.util.HashSet;
import java.util.Map;
import java.security.AccessController;
import java.security.Permission;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Optional;
+import java.util.ServiceLoader;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import static java.util.stream.Collectors.toMap;
+import java.util.stream.Stream;
import javax.management.JMX;
-import sun.management.ManagementFactoryHelper;
-import sun.management.ExtendedPlatformComponent;
+import sun.management.Util;
+import sun.management.spi.PlatformMBeanProvider;
+import sun.management.spi.PlatformMBeanProvider.PlatformComponent;
/**
* The {@code ManagementFactory} class is a factory class for getting
@@ -316,7 +321,7 @@
* the Java virtual machine.
*/
public static ClassLoadingMXBean getClassLoadingMXBean() {
- return ManagementFactoryHelper.getClassLoadingMXBean();
+ return getPlatformMXBean(ClassLoadingMXBean.class);
}
/**
@@ -326,7 +331,7 @@
* @return a {@link MemoryMXBean} object for the Java virtual machine.
*/
public static MemoryMXBean getMemoryMXBean() {
- return ManagementFactoryHelper.getMemoryMXBean();
+ return getPlatformMXBean(MemoryMXBean.class);
}
/**
@@ -336,7 +341,7 @@
* @return a {@link ThreadMXBean} object for the Java virtual machine.
*/
public static ThreadMXBean getThreadMXBean() {
- return ManagementFactoryHelper.getThreadMXBean();
+ return getPlatformMXBean(ThreadMXBean.class);
}
/**
@@ -347,7 +352,7 @@
*/
public static RuntimeMXBean getRuntimeMXBean() {
- return ManagementFactoryHelper.getRuntimeMXBean();
+ return getPlatformMXBean(RuntimeMXBean.class);
}
/**
@@ -360,7 +365,7 @@
* no compilation system.
*/
public static CompilationMXBean getCompilationMXBean() {
- return ManagementFactoryHelper.getCompilationMXBean();
+ return getPlatformMXBean(CompilationMXBean.class);
}
/**
@@ -371,7 +376,7 @@
* the Java virtual machine.
*/
public static OperatingSystemMXBean getOperatingSystemMXBean() {
- return ManagementFactoryHelper.getOperatingSystemMXBean();
+ return getPlatformMXBean(OperatingSystemMXBean.class);
}
/**
@@ -384,7 +389,7 @@
*
*/
public static List<MemoryPoolMXBean> getMemoryPoolMXBeans() {
- return ManagementFactoryHelper.getMemoryPoolMXBeans();
+ return getPlatformMXBeans(MemoryPoolMXBean.class);
}
/**
@@ -397,7 +402,7 @@
*
*/
public static List<MemoryManagerMXBean> getMemoryManagerMXBeans() {
- return ManagementFactoryHelper.getMemoryManagerMXBeans();
+ return getPlatformMXBeans(MemoryManagerMXBean.class);
}
@@ -413,7 +418,7 @@
*
*/
public static List<GarbageCollectorMXBean> getGarbageCollectorMXBeans() {
- return ManagementFactoryHelper.getGarbageCollectorMXBeans();
+ return getPlatformMXBeans(GarbageCollectorMXBean.class);
}
private static MBeanServer platformMBeanServer;
@@ -467,35 +472,11 @@
if (platformMBeanServer == null) {
platformMBeanServer = MBeanServerFactory.createMBeanServer();
- for (PlatformComponent pc : PlatformComponent.values()) {
- List<? extends PlatformManagedObject> list =
- pc.getMXBeans(pc.getMXBeanInterface());
- for (PlatformManagedObject o : list) {
- // Each PlatformComponent represents one management
- // interface. Some MXBean may extend another one.
- // The MXBean instances for one platform component
- // (returned by pc.getMXBeans()) might be also
- // the MXBean instances for another platform component.
- // e.g. com.sun.management.GarbageCollectorMXBean
- //
- // So need to check if an MXBean instance is registered
- // before registering into the platform MBeanServer
- if (!platformMBeanServer.isRegistered(o.getObjectName())) {
- addMXBean(platformMBeanServer, o);
- }
- }
- }
- HashMap<ObjectName, DynamicMBean> dynmbeans =
- ManagementFactoryHelper.getPlatformDynamicMBeans();
- for (Map.Entry<ObjectName, DynamicMBean> e : dynmbeans.entrySet()) {
- addDynamicMBean(platformMBeanServer, e.getValue(), e.getKey());
- }
- for (final PlatformManagedObject o :
- ExtendedPlatformComponent.getMXBeans()) {
- if (!platformMBeanServer.isRegistered(o.getObjectName())) {
- addMXBean(platformMBeanServer, o);
- }
- }
+ platformComponents()
+ .stream()
+ .filter(PlatformComponent::shouldRegister)
+ .flatMap(pc -> pc.nameToMBeanMap().entrySet().stream())
+ .forEach(entry -> addMXBean(platformMBeanServer, entry.getKey(), entry.getValue()));
}
return platformMBeanServer;
}
@@ -600,11 +581,8 @@
// bootstrap class loader
final Class<?> cls = mxbeanInterface;
ClassLoader loader =
- AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
- public ClassLoader run() {
- return cls.getClassLoader();
- }
- });
+ AccessController.doPrivileged(
+ (PrivilegedAction<ClassLoader>) () -> cls.getClassLoader());
if (!sun.misc.VM.isSystemDomainLoader(loader)) {
throw new IllegalArgumentException(mxbeanName +
" is not a platform MXBean");
@@ -619,7 +597,6 @@
" is not an instance of " + mxbeanInterface);
}
- final Class<?>[] interfaces;
// check if the registered MBean is a notification emitter
boolean emitter = connection.isInstanceOf(objName, NOTIF_EMITTER);
@@ -661,20 +638,11 @@
*/
public static <T extends PlatformManagedObject>
T getPlatformMXBean(Class<T> mxbeanInterface) {
- PlatformComponent pc = PlatformComponent.getPlatformComponent(mxbeanInterface);
- if (pc == null) {
- T mbean = ExtendedPlatformComponent.getMXBean(mxbeanInterface);
- if (mbean != null) {
- return mbean;
- }
- throw new IllegalArgumentException(mxbeanInterface.getName() +
- " is not a platform management interface");
- }
- if (!pc.isSingleton())
- throw new IllegalArgumentException(mxbeanInterface.getName() +
- " can have zero or more than one instances");
+ PlatformComponent<?> pc = PlatformMBeanFinder.findSingleton(mxbeanInterface);
- return pc.getSingletonMXBean(mxbeanInterface);
+ List<? extends T> mbeans = pc.getMBeans(mxbeanInterface);
+ assert mbeans.isEmpty() || mbeans.size() == 1;
+ return mbeans.isEmpty() ? null : mbeans.get(0);
}
/**
@@ -701,16 +669,19 @@
*/
public static <T extends PlatformManagedObject> List<T>
getPlatformMXBeans(Class<T> mxbeanInterface) {
- PlatformComponent pc = PlatformComponent.getPlatformComponent(mxbeanInterface);
+ // Validates at first the specified interface by finding at least one
+ // PlatformComponent whose MXBean implements this interface.
+ // An interface can be implemented by different MBeans, provided by
+ // different platform components.
+ PlatformComponent<?> pc = PlatformMBeanFinder.findFirst(mxbeanInterface);
if (pc == null) {
- T mbean = ExtendedPlatformComponent.getMXBean(mxbeanInterface);
- if (mbean != null) {
- return Collections.singletonList(mbean);
- }
- throw new IllegalArgumentException(mxbeanInterface.getName() +
- " is not a platform management interface");
+ throw new IllegalArgumentException(mxbeanInterface.getName()
+ + " is not a platform management interface");
}
- return Collections.unmodifiableList(pc.getMXBeans(mxbeanInterface));
+
+ return platformComponents().stream()
+ .flatMap(p -> p.getMBeans(mxbeanInterface).stream())
+ .collect(Collectors.toList());
}
/**
@@ -753,22 +724,8 @@
Class<T> mxbeanInterface)
throws java.io.IOException
{
- PlatformComponent pc = PlatformComponent.getPlatformComponent(mxbeanInterface);
- if (pc == null) {
- T mbean = ExtendedPlatformComponent.getMXBean(mxbeanInterface);
- if (mbean != null) {
- ObjectName on = mbean.getObjectName();
- return ManagementFactory.newPlatformMXBeanProxy(connection,
- on.getCanonicalName(),
- mxbeanInterface);
- }
- throw new IllegalArgumentException(mxbeanInterface.getName() +
- " is not a platform management interface");
- }
- if (!pc.isSingleton())
- throw new IllegalArgumentException(mxbeanInterface.getName() +
- " can have zero or more than one instances");
- return pc.getSingletonMXBean(connection, mxbeanInterface);
+ PlatformComponent<?> pc = PlatformMBeanFinder.findSingleton(mxbeanInterface);
+ return newPlatformMXBeanProxy(connection, pc.getObjectNamePattern(), mxbeanInterface);
}
/**
@@ -804,19 +761,56 @@
Class<T> mxbeanInterface)
throws java.io.IOException
{
- PlatformComponent pc = PlatformComponent.getPlatformComponent(mxbeanInterface);
+ // Validates at first the specified interface by finding at least one
+ // PlatformComponent whose MXBean implements this interface.
+ // An interface can be implemented by different MBeans, provided by
+ // different platform components.
+ PlatformComponent<?> pc = PlatformMBeanFinder.findFirst(mxbeanInterface);
if (pc == null) {
- T mbean = ExtendedPlatformComponent.getMXBean(mxbeanInterface);
- if (mbean != null) {
- ObjectName on = mbean.getObjectName();
- T proxy = ManagementFactory.newPlatformMXBeanProxy(connection,
- on.getCanonicalName(), mxbeanInterface);
- return Collections.singletonList(proxy);
+ throw new IllegalArgumentException(mxbeanInterface.getName()
+ + " is not a platform management interface");
+ }
+
+ // Collect all names, eliminate duplicates.
+ Stream<String> names = Stream.empty();
+ for (PlatformComponent<?> p : platformComponents()) {
+ names = Stream.concat(names, getProxyNames(p, connection, mxbeanInterface));
+ }
+ Set<String> objectNames = names.collect(Collectors.toSet());
+ if (objectNames.isEmpty()) return Collections.emptyList();
+
+ // Map names on proxies.
+ List<T> proxies = new ArrayList<>();
+ for (String name : objectNames) {
+ proxies.add(newPlatformMXBeanProxy(connection, name, mxbeanInterface));
+ }
+ return proxies;
+ }
+
+ // Returns a stream containing all ObjectNames of the MBeans represented by
+ // the specified PlatformComponent and implementing the specified interface.
+ // If the PlatformComponent is a singleton, the name returned by
+ // PlatformComponent.getObjectNamePattern() will be used, otherwise
+ // we will query the specified MBeanServerConnection (conn.queryNames)
+ // with the pattern returned by PlatformComponent.getObjectNamePattern()
+ // in order to find the names of matching MBeans.
+ // In case of singleton, we do not check whether the MBean is registered
+ // in the connection because the caller "getPlatformMXBeans" will do the check
+ // when creating a proxy.
+ private static Stream<String> getProxyNames(PlatformComponent<?> pc,
+ MBeanServerConnection conn,
+ Class<?> intf)
+ throws IOException
+ {
+ if (pc.mbeanInterfaceNames().contains(intf.getName())) {
+ if (pc.isSingleton()) {
+ return Stream.of(pc.getObjectNamePattern());
+ } else {
+ return conn.queryNames(Util.newObjectName(pc.getObjectNamePattern()), null)
+ .stream().map(ObjectName::getCanonicalName);
}
- throw new IllegalArgumentException(mxbeanInterface.getName() +
- " is not a platform management interface");
}
- return Collections.unmodifiableList(pc.getMXBeans(connection, mxbeanInterface));
+ return Stream.empty();
}
/**
@@ -835,63 +829,145 @@
public static Set<Class<? extends PlatformManagedObject>>
getPlatformManagementInterfaces()
{
- Set<Class<? extends PlatformManagedObject>> result =
- new HashSet<>();
- for (PlatformComponent component: PlatformComponent.values()) {
- result.add(component.getMXBeanInterface());
- }
- return Collections.unmodifiableSet(result);
+ return platformComponents()
+ .stream()
+ .flatMap(pc -> pc.mbeanInterfaces().stream())
+ .filter(clazz -> PlatformManagedObject.class.isAssignableFrom(clazz))
+ .map(clazz -> clazz.asSubclass(PlatformManagedObject.class))
+ .collect(Collectors.toSet());
}
private static final String NOTIF_EMITTER =
"javax.management.NotificationEmitter";
- /**
- * Registers an MXBean.
- */
- private static void addMXBean(final MBeanServer mbs, final PlatformManagedObject pmo) {
- // Make DynamicMBean out of MXBean by wrapping it with a StandardMBean
+ private static void addMXBean(final MBeanServer mbs, String name, final Object pmo)
+ {
try {
- AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
- public Void run() throws InstanceAlreadyExistsException,
- MBeanRegistrationException,
- NotCompliantMBeanException {
- final DynamicMBean dmbean;
- if (pmo instanceof DynamicMBean) {
- dmbean = DynamicMBean.class.cast(pmo);
- } else if (pmo instanceof NotificationEmitter) {
- dmbean = new StandardEmitterMBean(pmo, null, true, (NotificationEmitter) pmo);
- } else {
- dmbean = new StandardMBean(pmo, null, true);
- }
+ ObjectName oname = ObjectName.getInstance(name);
+ // Make DynamicMBean out of MXBean by wrapping it with a StandardMBean
+ AccessController.doPrivileged((PrivilegedExceptionAction<Void>) () -> {
+ final DynamicMBean dmbean;
+ if (pmo instanceof DynamicMBean) {
+ dmbean = DynamicMBean.class.cast(pmo);
+ } else if (pmo instanceof NotificationEmitter) {
+ dmbean = new StandardEmitterMBean(pmo, null, true, (NotificationEmitter) pmo);
+ } else {
+ dmbean = new StandardMBean(pmo, null, true);
+ }
- mbs.registerMBean(dmbean, pmo.getObjectName());
- return null;
- }
+ mbs.registerMBean(dmbean, oname);
+ return null;
});
+ } catch (MalformedObjectNameException mone) {
+ throw new IllegalArgumentException(mone);
} catch (PrivilegedActionException e) {
throw new RuntimeException(e.getException());
}
}
- /**
- * Registers a DynamicMBean.
- */
- private static void addDynamicMBean(final MBeanServer mbs,
- final DynamicMBean dmbean,
- final ObjectName on) {
- try {
- AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
- @Override
- public Void run() throws InstanceAlreadyExistsException,
- MBeanRegistrationException,
- NotCompliantMBeanException {
- mbs.registerMBean(dmbean, on);
- return null;
- }
- });
- } catch (PrivilegedActionException e) {
- throw new RuntimeException(e.getException());
+ private static Collection<PlatformComponent<?>> platformComponents()
+ {
+ return PlatformMBeanFinder.getMap().values();
+ }
+
+ private static class PlatformMBeanFinder
+ {
+ private static final Map<String, PlatformComponent<?>> componentMap;
+ static {
+ // get all providers
+ List<PlatformMBeanProvider> providers = AccessController.doPrivileged(
+ (PrivilegedAction<List<PlatformMBeanProvider>>) () -> {
+ List<PlatformMBeanProvider> all = new ArrayList<>();
+ ServiceLoader.loadInstalled(PlatformMBeanProvider.class)
+ .forEach(all::add);
+ all.add(new DefaultPlatformMBeanProvider());
+ return all;
+ }, null, new FilePermission("<<ALL FILES>>", "read"),
+ new RuntimePermission("sun.management.spi.PlatformMBeanProvider"));
+
+ // load all platform components into a map
+ componentMap = providers.stream()
+ .flatMap(p -> toPlatformComponentStream(p))
+ // The first one wins if multiple PlatformComponents
+ // with same ObjectName pattern,
+ .collect(toMap(PlatformComponent::getObjectNamePattern,
+ Function.identity(),
+ (p1, p2) -> p1));
+ }
+
+ static Map<String, PlatformComponent<?>> getMap() {
+ return componentMap;
+ }
+
+ // Loads all platform components from a provider into a stream
+ // Ensures that two different components are not declared with the same
+ // object name pattern. Throws InternalError if the provider incorrectly
+ // declares two platform components with the same pattern.
+ private static Stream<PlatformComponent<?>>
+ toPlatformComponentStream(PlatformMBeanProvider provider)
+ {
+ return provider.getPlatformComponentList()
+ .stream()
+ .collect(toMap(PlatformComponent::getObjectNamePattern,
+ Function.identity(),
+ (p1, p2) -> {
+ throw new InternalError(
+ p1.getObjectNamePattern() +
+ " has been used as key for " + p1 +
+ ", it cannot be reused for " + p2);
+ }))
+ .values().stream();
+ }
+
+ // Finds the first PlatformComponent whose mbeanInterfaceNames() list
+ // contains the specified class name. An MBean interface can be implemented
+ // by different MBeans, provided by different platform components.
+ // For instance the MemoryManagerMXBean interface is implemented both by
+ // regular memory managers, and garbage collector MXBeans. This method is
+ // mainly used to verify that there is at least one PlatformComponent
+ // which provides an implementation of the desired interface.
+ static PlatformComponent<?> findFirst(Class<?> mbeanIntf)
+ {
+ String name = mbeanIntf.getName();
+ Optional<PlatformComponent<?>> op = getMap().values()
+ .stream()
+ .filter(pc -> pc.mbeanInterfaceNames().contains(name))
+ .findFirst();
+
+ if (op.isPresent()) {
+ return op.get();
+ } else {
+ return null;
+ }
+ }
+
+ // Finds a PlatformComponent whose mbeanInterface name list contains
+ // the specified class name, and make sure that one and only one exists.
+ static PlatformComponent<?> findSingleton(Class<?> mbeanIntf)
+ {
+ String name = mbeanIntf.getName();
+ Optional<PlatformComponent<?>> op = getMap().values()
+ .stream()
+ .filter(pc -> pc.mbeanInterfaceNames().contains(name))
+ .reduce((p1, p2) -> {
+ if (p2 != null) {
+ throw new IllegalArgumentException(mbeanIntf.getName() +
+ " can have more than one instance");
+ } else {
+ return p1;
+ }
+ });
+
+ PlatformComponent<?> singleton = op.isPresent() ? op.get() : null;
+ if (singleton == null) {
+ throw new IllegalArgumentException(mbeanIntf.getName() +
+ " is not a platform management interface");
+ }
+ if (!singleton.isSingleton()) {
+ throw new IllegalArgumentException(mbeanIntf.getName() +
+ " can have more than one instance");
+ }
+ return singleton;
}
}
}