除了可以在HTML中管理MBean之外,我们还可以通过程序来连接JMX管理MBean。这就需要用到了JMX的Connectior,JMX提供了两种Connector:RMI Connector和JMXMP Connector(JMX message protocol Connector)。下面介绍RMI Connector。
首先还是要创建MBean接口和实现
package com.jmx.client;
public interface HelloMBean {
public String getName();
public void setName(String name);
public void helloWorld();
public void helloWorld(String name);
public String getTelephone();
}
package com.jmx.client;
public interface HelloMBean {
public String getName();
public void setName(String name);
public void helloWorld();
public void helloWorld(String name);
public String getTelephone();
}
package com.jmx.client;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.net.MalformedURLException;
import java.rmi.registry.LocateRegistry;
import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
import javax.management.remote.JMXConnectorServer;
import javax.management.remote.JMXConnectorServerFactory;
import javax.management.remote.JMXServiceURL;
import com.sun.jdmk.comm.HtmlAdaptorServer;
public class HelloAgent {
public static void main(String[] args) throws MalformedObjectNameException, NullPointerException, InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException {
//create mbean server
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
//create object name
ObjectName helloName = new ObjectName("jmxBean:name=hello");
//create mbean and register mbean
server.registerMBean(new Hello(), helloName);
//create adaptor, adaptor is just a form as show mbean. It has no relation to specific mbean.
HtmlAdaptorServer adaptor = new HtmlAdaptorServer();
//create adaptor name
ObjectName adaptorName = new ObjectName("jmxAdaptor:name=adaptor,port=5050");
//register adaptor and adaptor name
server.registerMBean(adaptor, adaptorName);
adaptor.setPort(9999);
adaptor.start();
System.out.println("....................server start....................");
//JMXConnectorServer service
try {
//这句话非常重要,不能缺少!注册一个端口,绑定url后,客户端就可以使用rmi通过url方式来连接JMXConnectorServer
LocateRegistry.createRegistry(8888);
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:8888/server");
JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer(url, null, server);
System.out.println("....................begin rmi start.....");
cs.start();
System.out.println("....................rmi start.....");
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
这里的8888(默认为1099)是通讯端口或者查找端口,服务端在createRegistry时实际上会new ServerSocket(8888),客户端的socket通过与端口号为8888的服务端端口互联lookup到server对象。客户端获取到的server对象在和服务端的sketon对象进行通讯时实际上也会建立socket连接,数据传输时的ServerSocket也需要一个端口(不同于通讯端口),称之为数据端口。
package com.jmx.client;
import java.util.Iterator;
import java.util.Set;
import javax.management.Attribute;
import javax.management.MBeanInfo;
import javax.management.MBeanServerConnection;
import javax.management.MBeanServerInvocationHandler;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import com.jmx.demo.HelloMBean;
public class Client {
public static void main(String[] args) throws Exception {
//connect JMX
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:8888/server");
JMXConnector jmxc = JMXConnectorFactory.connect(url,null);
MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();
ObjectName mbeanName = new ObjectName("jmxBean:name=hello");
//print domains
System.out.println("Domains:---------------");
String domains[] = mbsc.getDomains();
for (int i = 0; i < domains.length; i++) {
System.out.println("\tDomain[" + i +"] = " + domains[i]);
}
//MBean count
System.out.println("MBean count = " + mbsc.getMBeanCount());
//process attribute
mbsc.setAttribute(mbeanName, new Attribute("Name", "new value"));//set value
System.out.println("Name = " + mbsc.getAttribute(mbeanName, "Name"));//get value
//invoke via proxy
HelloMBean proxy = (HelloMBean) MBeanServerInvocationHandler.newProxyInstance(mbsc, mbeanName, HelloMBean.class, false);
proxy.helloWorld();
proxy.helloWorld("I'll connect to JMX Server via client.");
//invoke via rmi
mbsc.invoke(mbeanName, "helloWorld", null, null);
mbsc.invoke(mbeanName, "helloWorld", new Object[] { "I'll connect to JMX Server via client2." }, new String[] { String.class.getName() });
//get mbean information
MBeanInfo info = mbsc.getMBeanInfo(mbeanName);
System.out.println("Hello Class:" + info.getClassName());
System.out.println("Hello Attriber:" + info.getAttributes()[0].getName());
System.out.println("Hello Operation:" + info.getOperations()[0].getName());
//ObjectName of MBean
System.out.println("all ObjectName:---------------");
Set set = mbsc.queryMBeans(null, null);
for (Iterator it = set.iterator(); it.hasNext();) {
ObjectInstance oi = (ObjectInstance)it.next();
System.out.println("\t" + oi.getObjectName());
}
jmxc.close();
}
}