Java 管理扩展(Java Management Extension,JMX)是从jdk1.4开始的,但从1.5时才加到jdk里面,并把API放到java.lang.management包里面。
如果一个 Java 对象可以由一个遵循 JMX 规范的管理器应用管理,那么这个Java 对象就可以称为一个可由 JMX 管理的资源。
要使一个 Java 对象可管理,则必须创建相应的 MBean 对象,并通过这些 MBean 对象管理相应的 Java 对象。当拥有 MBean 类后,需要将其实例化并注册到 MBeanServer 上。
一共有四种类型的 MBean , 分别是标准类型 MBean, 动态类型 MBean, 开放类型 MBean 和模型类型 MBean。
注:
- 一个java进程里面可以有多个不同名字的mBeanServer ,每个mbs都是一个独立的容器,用了管理mbean
- 每个mbs都可以注册多个rmi port,http port等
- platformMBeanServer 是由jvm创建的,并添加了一些系统的mbean,如cpu,内存,网络,线程等等
1、本机使用
当我们启动java进程后,经常会使用jps,jinfo,jmap,jstat等jdk自带的命令去查询进程的状态,这其中的原理就是,当java进程启动后,会创建一个用于本机连接的“localConnectorAddress”放到当前用户目录下,当使用jps等连接时,会到当前用户目录下取到“localConnectorAddress”并连接。
@Test
public void test1() {
List<VirtualMachineDescriptor> vms = VirtualMachine.list();
for (VirtualMachineDescriptor desc : vms) {
VirtualMachine vm;
try {
System.out.println("desc:" + desc);
System.out.println("进程id:"+desc.id());
vm = VirtualMachine.attach(desc);
} catch (Exception e) {
e.printStackTrace();
continue;
}
JMXConnector connector = null;
try {
Properties props = vm.getAgentProperties();
for (Map.Entry<Object, Object> entry : props.entrySet()) {
System.out.println(entry.getKey() + "->" + entry.getValue());
}
String connectorAddress = props.getProperty("com.sun.management.jmxremote.localConnectorAddress");
if (connectorAddress == null) {
System.out.println("connectorAddress is null");
continue;
}
System.out.println("conn:" + connectorAddress);
//以下代码用于连接指定的jmx,本地或者远程
JMXServiceURL url = new JMXServiceURL(connectorAddress);
//JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:1099/TestJMXServer");
connector = JMXConnectorFactory.connect(url);
MBeanServerConnection mbeanConn = connector.getMBeanServerConnection();
Set<ObjectName> beanSet = mbeanConn.queryNames(null, null);
// ...
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (connector != null) connector.close();
break;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
需要注意的是,上面代码需要把tools.jar放到classpath里面。
上面代码有时候取不到本地连接地址,这个时候需要尝试让agent加载management-agent.jar,完整代码如下:
package cn.myroute.mbean;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java