场景
使用 jconsole
visualvm
jmc
等工具连接本地的 java 进程时,会使用 jmx 的通信机制进行通信。
通信方式
以下样例代码解释了 jmx 通信的核心流程
// 1. 获取所有 java 进程
List<VirtualMachineDescriptor> list = VirtualMachine.list();
int index = 0;
VirtualMachine vm = VirtualMachine.attach(list.get(index));
// 2. 获取 jmx 通信地址
Properties props = vm.getAgentProperties();
String connectorAddress = props.getProperty("com.sun.management.jmxremote.localConnectorAddress");
JMXServiceURL url = new JMXServiceURL(connectorAddress);
JMXConnector jmxConnector = JMXConnectorFactory.connect(url);
// 3. 远程方法调用
MBeanServerConnection mbsc = jmxConnector.getMBeanServerConnection();
String result = (String) mbsc.invoke(new ObjectName("objectName"), "functionName", new Object[]{}, new String[]{});
1. 获取所有 java 进程
类似于 jps
的功能,借助于 hsperfdata 文件获取所有 java 进程的pid
每个java进程启动时,都会在系统的临时文件目录下创建一个以pid为文件名的hsperfdata文件。这个目录下的所有文件代表了所有 java 进程的 pid。
- Linux
/tmp/hsperfdata_{user_name}/{pid}
- Windows
{user_dir}\AppData\Local\Temp\hsperfdata_{user_name}\{pid}
假设用户名为 userabcd,pid 为 1234,实际文件名如下
- Linux
/tmp/hsperfdata_userabcd/1234
- Windows
C:\Users\userabcd\AppData\Local\Temp\hsperfdata_userabcd\1234
2. 获取 jmx 通信地址
使用进程间通信获取 agentProperties,从agentProperties中获取com.sun.management.jmxremote.localConnectorAddress
key,即为 jmx 通信地址
进程间通信的方式
- Linux
UNIX socket - Windows
Windows pipe
通过进程间通信,向 jvm 发送 agentProperties
命令,jvm回复的属性中包含了jmx 通信地址,地址格式如下
service:jmx:rmi://127.0.0.1/stub/{base64}
3. 远程方法调用
jmx 通信地址中包含了使用哪种通信协议,jndi
或是jrmp
例如 jmx 通信地址
service:jmx:rmi://127.0.0.1/stub/{base64}
中的 stub
代表 jrmp
协议,之后的 {base64} 编码字符串中包含了用于 jrmp
协议通信的 host 和 port。
至此,可以使用 jrmp
协议进行通信(远程方法调用)
网友评论