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;
}