JMXMP简单介绍
JMXMP(Java Management Extensions Message Protocol)是Java Management Extensions (JMX) 技术中用于远程通信的一种协议。它定义了一种基于TCP/IP的二进制消息格式,用于在JMX客户端和JMX代理(或服务器)之间交换JMX操作。
使用的JDK1.8
开启jmx(JMXMP协议)
jmxmp并非java的标准包中的内容,无论是客户端还是服务端,都需要单独引入其jar。
<dependency>
<groupId>org.glassfish.external</groupId>
<artifactId>opendmk_jmxremote_optional_jar</artifactId>
<version>1.0-b01-ea</version>
</dependency>
服务端代码
- 与平时的rmi区别在于,需要额外启动一个
JMXConnectorServer
,这个服务会常驻,用来接受和转发客户端的请求。
import javax.management.*;
import javax.management.remote.JMXConnectorServer;
import javax.management.remote.JMXConnectorServerFactory;
import javax.management.remote.JMXServiceURL;
import java.io.IOException;
import java.lang.management.ManagementFactory;
/**
* @version 1.0
*/
public class JMXServer {
public static void main(String[] args) throws InterruptedException, IOException {
//获取MBean Server
MBeanServer platformMBeanServer = ManagementFactory.getPlatformMBeanServer();
// 让服务端JVM支持jmxmp需要开启jmxmp的JMXConnectorServer
// 设置JMXMP连接器地址
JMXServiceURL url = new JMXServiceURL("jmxmp", "localhost", 1099);
// 创建JMXMP连接器服务器并启动
JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer(url, null, platformMBeanServer);
cs.start();
//创建【实现类】服务
MyMemory myMemory = new MyMemory();
myMemory.setTotal(100L);
myMemory.setUsed(20L);
//注册服务到MBean Server
ObjectName objectName = new ObjectName("com.example.test.bean:type=myMemory");
platformMBeanServer.registerMBean(myMemory, objectName);
while (true) {
Thread.sleep(5000);
System.out.println("alive...");
}
}
}
可以在开启服务后注册MBean并操作其中的属性值
//创建【实现类】服务
MyMemory myMemory = new MyMemory();
myMemory.setTotal(100L);
myMemory.setUsed(20L);
//注册服务到MBean Server
ObjectName objectName = new ObjectName("com.example.test.bean:type=myMemory");
platformMBeanServer.registerMBean(myMemory, objectName);
启动服务端的时候需要增加VM选项
开启jmx
-Dcom.sun.management.jmxremote.port=9999
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
客户端代码
查询内置MemoryPool情况
import javax.management.*;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* @version 1.0
*/
public class JMXClient {
public static void main(String[] args) throws IOException, MalformedObjectNameException, ReflectionException, InstanceNotFoundException, IntrospectionException, AttributeNotFoundException, MBeanException {
// JMX Service URL指向JMXMP协议的服务端地址
JMXServiceURL jmxServiceURL = new JMXServiceURL("jmxmp", "127.0.0.1", 1099);
// 创建连接
Map<String, Object> environment = new HashMap<>();
// 如果需要认证,可以在此处设置用户名和密码
// environment.put("jmx.remote.credentials", new String[] { "user", "password" });
JMXConnector connector = JMXConnectorFactory.connect(jmxServiceURL, environment);
// 连接成功后,可以获取MBeanServerConnection来进行管理操作
MBeanServerConnection mbeanServerConnection = connector.getMBeanServerConnection();
ObjectName objectName = new ObjectName("java.lang:type=MemoryPool,name=*");
Set<ObjectName> objectNames = mbeanServerConnection.queryNames(objectName, null);
for (ObjectName name : objectNames) {
System.out.println("name=" + name);
MBeanInfo minfo = mbeanServerConnection.getMBeanInfo(name);
MBeanAttributeInfo[] beanAttributeInfos = minfo.getAttributes();
Object value;
for (MBeanAttributeInfo attributeInfo : beanAttributeInfos) {
try {
value = mbeanServerConnection.getAttribute(name, attributeInfo.getName());
System.out.println(attributeInfo.getName() + " " + value);
} catch (Exception e) {
System.out.println(attributeInfo.getName() + " 其值不可用");
}
}
}
// 使用完成后关闭连接
connector.close();
}
}
查询自定义com.example.test.bean:type=myMemory
情况
import javax.management.*;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* @version 1.0
*/
public class JMXClient {
public static void main(String[] args) throws IOException, MalformedObjectNameException, ReflectionException, InstanceNotFoundException, IntrospectionException, AttributeNotFoundException, MBeanException {
// JMX Service URL指向JMXMP协议的服务端地址
JMXServiceURL jmxServiceURL = new JMXServiceURL("jmxmp", "127.0.0.1", 1099);
// 创建连接
Map<String, Object> environment = new HashMap<>();
// 如果需要认证,可以在此处设置用户名和密码
// environment.put("jmx.remote.credentials", new String[] { "user", "password" });
JMXConnector connector = JMXConnectorFactory.connect(jmxServiceURL, environment);
// 连接成功后,可以获取MBeanServerConnection来进行管理操作
MBeanServerConnection mbeanServerConnection = connector.getMBeanServerConnection();
ObjectName objectName = new ObjectName("com.example.test.bean:type=*");
Set<ObjectName> objectNames = mbeanServerConnection.queryNames(objectName, null);
for (ObjectName name : objectNames) {
System.out.println("name=" + name);
MBeanInfo minfo = mbeanServerConnection.getMBeanInfo(name);
MBeanAttributeInfo[] beanAttributeInfos = minfo.getAttributes();
Object value;
for (MBeanAttributeInfo attributeInfo : beanAttributeInfos) {
try {
value = mbeanServerConnection.getAttribute(name, attributeInfo.getName());
System.out.println(attributeInfo.getName() + " " + value);
} catch (Exception e) {
System.out.println(attributeInfo.getName() + " 其值不可用");
}
}
}
// 使用完成后关闭连接
connector.close();
}
}
JMX内置的JVM资源检测
资源接口 | 监测的资源 | ObjectName |
---|---|---|
ClassLoadingMXBean | 类加载 | name=java.lang:type=ClassLoading |
CompilationMXBean | 汇编系统 | name=java.lang:type=Compilation |
GarbageCollectorMXBean | 垃圾回收 | name=java.lang:type=GarbageCollector,name=XXX |
MemoryManagerMXBean | 内存管理 | name=java.lang:type= MemoryManager,name=XXX |
MemoryPoolMXBean | 内存池管理 | name=java.lang:type=MemoryPool,name=XXX |
ThreadMXBean | 线程情况 | name=java.lang:type=Threading |
RuntimeMXBean | 运行时情况 | name=java.lang:type=Runtime |
OperatingSystemMXBean | 操作系统情况 | name=java.lang:type=OperatingSystem |
彩蛋
当rmi协议不可用的时候,可以使用jmxmp协议。
rmi为啥不可用了?
- 低版本的JBOSS/wildfly(8.2以下)的配置文件中,没有主动开启rmi时,或者无法开启时。
JBOSS和wildfly机器上对其他服务进行jmx访问(rmi协议)。需要增加中配置后才能正常使用。配置~/wildfly/modules/system/layers/base/sun/jdk/main/module.xml中增加<path name="com/sun/jndi/url/rmi"/>
- 防火墙禁止了rmi协议