import java.io.IOException; import java.lang.reflect.Method; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import java.rmi.server.UnicastRemoteObject; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicBoolean; import javax.management.InstanceNotFoundException; import javax.management.JMException; import javax.management.MBeanServer; import javax.management.MBeanServerFactory; import javax.management.MBeanServerInvocationHandler; import javax.management.MalformedObjectNameException; import javax.management.ObjectInstance; import javax.management.ObjectName; import javax.management.QueryExp; import javax.management.remote.JMXConnectorServer; import javax.management.remote.JMXConnectorServerFactory; import javax.management.remote.JMXServiceURL; public class ManagementContext implements Service { private MBeanServer beanServer; private final AtomicBoolean started = new AtomicBoolean(false); private String connectorHost = "localhost"; private int connectorPort = 1099; private final AtomicBoolean connectorStarting = new AtomicBoolean(false); public ManagementContext() { this(null); } public ManagementContext(MBeanServer server) { this.beanServer = server; } @Override public void start() throws Exception { if(started.compareAndSet(false, true)) { if(connectorHost == null) { connectorHost = "localhost"; } getMBeanServer(); if(connectorServer != null) { try { if(getMBeanServer().isRegistered(namingServiceObjectName)) { getMBeanServer().invoke(namingServiceObjectName, "start", null, null); } } catch(Throwable ignore) { // log exception info } } Thread thread = new Thread("JMX connector") { public void run() { try { JMXConnectorServer server = connectorServer; if(started.get() && server != null) { System.out.println("Starting JMXConnectorServer..."); connectorStarting.set(true); try { server.start(); } finally { connectorStarting.set(false); } } } catch(IOException e) { e.printStackTrace(); } finally { // } } }; thread.setDaemon(true); thread.start(); } } protected MBeanServer getMBeanServer() { if(this.beanServer == null) { this.beanServer = findMBeanServer(); } return beanServer; } private boolean useMBeanServer = true; private boolean createMBeanServer = true; private boolean findTigerMbeanServer = true; private boolean createConnector = true; protected synchronized MBeanServer findMBeanServer() { MBeanServer result = null; try { if(useMBeanServer) { if(findTigerMbeanServer) { result = findTigerMBeanServer(); } if(result == null) { List<MBeanServer> list = MBeanServerFactory.findMBeanServer(null); if(list != null && list.size() > 0) { result = list.get(0); } } if(result == null && createMBeanServer) { result = createMBeanServer(); } } } catch(NoClassDefFoundError e) { // log exception e.printStackTrace(); } catch (Throwable e) { // log info e.printStackTrace(); } return result; } private static final String DEFAULT_DOMAIN = "org.fantasy"; private String jmxDomainName = DEFAULT_DOMAIN; private boolean locallyCreateMBeanServer; protected MBeanServer createMBeanServer() throws MalformedObjectNameException, NullPointerException, IOException { MBeanServer mbeanServer = MBeanServerFactory.createMBeanServer(jmxDomainName); locallyCreateMBeanServer = true; if(createConnector) { createConnector(mbeanServer); } return mbeanServer; } public MBeanServer findTigerMBeanServer() { String name = "java.lang.management.ManagementFactory"; Class<?> type = loadClass(name, ManagementContext.class.getClassLoader()); if(type != null) { try { Method method = type.getDeclaredMethod("getPlatformMBeanServer", new Class[0]); if(method != null) { Object answer = method.invoke(null, new Object[0]); if(answer instanceof MBeanServer) { if(createConnector) { createConnector((MBeanServer)answer); } return (MBeanServer)answer; } else { // log info } } else { // log info } } catch (Exception e) { // log exception } } else { // log info } return null; } private Registry registry; private ObjectName namingServiceObjectName; private int rmiServerPort; private String connectorPath = "/jmxrmi"; private Map<String, ?> environment; private JMXConnectorServer connectorServer; private void createConnector(MBeanServer mbeanServer) throws IOException, MalformedObjectNameException, NullPointerException { if(registry == null) { registry = LocateRegistry.createRegistry(connectorPort); } namingServiceObjectName = ObjectName.getInstance("naming:type=rmiregistry"); String rmiServer = ""; if(rmiServerPort != 0) { rmiServer = "" + getConnectorHost() + ":" + rmiServerPort; } /** service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi */ String serviceURL = "service:jmx:rmi://" + rmiServer + "/jndi/rmi://" +getConnectorHost()+":" + connectorPort + connectorPath; JMXServiceURL url = new JMXServiceURL(serviceURL); connectorServer = JMXConnectorServerFactory.newJMXConnectorServer(url, environment, mbeanServer); } public int getConnectorPort() { return connectorPort; } public String getConnectorHost() { return connectorHost; } private final Map<ObjectName, ObjectName> registeredMBeanNames = new ConcurrentHashMap<ObjectName, ObjectName>(); public void stop() throws Exception { if(started.compareAndSet(true, false)) { MBeanServer mbeanServer = getMBeanServer(); if(mbeanServer != null) { for (Map.Entry<ObjectName, ObjectName> entry : registeredMBeanNames.entrySet()) { ObjectName actualName = entry.getValue(); if (actualName != null && beanServer.isRegistered(actualName)) { mbeanServer.unregisterMBean(actualName); } } } registeredMBeanNames.clear(); JMXConnectorServer server = connectorServer; connectorServer = null; if(server != null) { if(!connectorStarting.get()) { server.stop(); } } if(namingServiceObjectName != null && getMBeanServer().isRegistered(namingServiceObjectName)) { getMBeanServer().invoke(namingServiceObjectName, "stop", null, null); getMBeanServer().unregisterMBean(namingServiceObjectName); } namingServiceObjectName = null; if(locallyCreateMBeanServer && beanServer != null) { List<MBeanServer> list = MBeanServerFactory.findMBeanServer(null); if(list != null && !list.isEmpty() && list.contains(beanServer)) { MBeanServerFactory.releaseMBeanServer(mbeanServer); } } beanServer = null; } if(registry != null) { UnicastRemoteObject.unexportObject(registry, true); registry = null; } } private static Class<?> loadClass(String name, ClassLoader loader) { try { return loader.loadClass(name); } catch (ClassNotFoundException e) { try { return Thread.currentThread().getContextClassLoader().loadClass(name); } catch (ClassNotFoundException e1) { return null; } } } public ObjectName createCustomComponentMBeanName(String type, String name) { ObjectName result = null; String tmp = jmxDomainName + ":" + "type=" + sanitizeString(type) + ",name=" + sanitizeString(name); try { result = new ObjectName(tmp); } catch (MalformedObjectNameException e) { e.printStackTrace(); // exception } return result; } public Object getAttribute(ObjectName name, String attribute) throws Exception { return getMBeanServer().getAttribute(name, attribute); } public Object newProxyInstance(ObjectName objectName, Class<?> interfaceClass, boolean notificationBroadcaster) { return MBeanServerInvocationHandler.newProxyInstance(getMBeanServer(), objectName, interfaceClass, notificationBroadcaster); } public ObjectInstance registerMBean(Object bean, ObjectName name) throws Exception { ObjectInstance result = getMBeanServer().registerMBean(bean, name); this.registeredMBeanNames.put(name, result.getObjectName()); return result; } public Set<ObjectName> queryNames(ObjectName name, QueryExp query) throws Exception { if (name != null) { ObjectName actualName = this.registeredMBeanNames.get(name); if(actualName != null) { return getMBeanServer().queryNames(actualName, query); } } return getMBeanServer().queryNames(name, query); } private static String sanitizeString(String in) { String result = null; if (in != null) { result = in.replace(':', '_'); result = result.replace('/', '_'); result = result.replace('\\', '_'); } return result; } public ObjectInstance getObjectInstance(ObjectName name) throws InstanceNotFoundException { return getMBeanServer().getObjectInstance(name); } public void unregisterMBean(ObjectName name) throws JMException { ObjectName actualName = this.registeredMBeanNames.get(name); if ( beanServer != null && actualName != null && beanServer.isRegistered(actualName) && this.registeredMBeanNames.remove(name) != null ) { beanServer.unregisterMBean(actualName); } } public static void main(String[] args) throws Exception { ManagementContext managementContext = new ManagementContext(); managementContext.start(); ObjectName objectName = managementContext.createCustomComponentMBeanName("20160113", "1507"); Hello hello = new Hello(); ObjectInstance objectInstance = managementContext.registerMBean(hello, objectName); objectInstance.getClassName(); String name = (String)managementContext.getAttribute(objectName, "Name"); System.out.println(name); Set<ObjectName> names = managementContext.queryNames(objectName, null); for(ObjectName oName : names) { System.out.println(oName); } // managementContext.stop(); Thread.sleep(Long.MAX_VALUE); } }
public interface Service { public void start() throws Exception; public void stop() throws Exception; }