JMX本地通信

场景

使用 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 协议进行通信(远程方法调用)

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容