場(chǎng)景
使用 jconsole
visualvm
jmc
等工具連接本地的 java 進(jìn)程時(shí)醋火,會(huì)使用 jmx 的通信機(jī)制進(jìn)行通信。
通信方式
以下樣例代碼解釋了 jmx 通信的核心流程
// 1. 獲取所有 java 進(jìn)程
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. 遠(yuǎn)程方法調(diào)用
MBeanServerConnection mbsc = jmxConnector.getMBeanServerConnection();
String result = (String) mbsc.invoke(new ObjectName("objectName"), "functionName", new Object[]{}, new String[]{});
1. 獲取所有 java 進(jìn)程
類似于 jps
的功能,借助于 hsperfdata 文件獲取所有 java 進(jìn)程的pid
每個(gè)java進(jìn)程啟動(dòng)時(shí)狸吞,都會(huì)在系統(tǒng)的臨時(shí)文件目錄下創(chuàng)建一個(gè)以pid為文件名的hsperfdata文件胆描。這個(gè)目錄下的所有文件代表了所有 java 進(jìn)程的 pid。
- Linux
/tmp/hsperfdata_{user_name}/{pid}
- Windows
{user_dir}\AppData\Local\Temp\hsperfdata_{user_name}\{pid}
假設(shè)用戶名為 userabcd醋粟,pid 為 1234靡菇,實(shí)際文件名如下
- Linux
/tmp/hsperfdata_userabcd/1234
- Windows
C:\Users\userabcd\AppData\Local\Temp\hsperfdata_userabcd\1234
2. 獲取 jmx 通信地址
使用進(jìn)程間通信獲取 agentProperties,從agentProperties中獲取com.sun.management.jmxremote.localConnectorAddress
key米愿,即為 jmx 通信地址
進(jìn)程間通信的方式
- Linux
UNIX socket - Windows
Windows pipe
通過進(jìn)程間通信厦凤,向 jvm 發(fā)送 agentProperties
命令,jvm回復(fù)的屬性中包含了jmx 通信地址育苟,地址格式如下
service:jmx:rmi://127.0.0.1/stub/{base64}
3. 遠(yuǎn)程方法調(diào)用
jmx 通信地址中包含了使用哪種通信協(xié)議较鼓,jndi
或是jrmp
例如 jmx 通信地址
service:jmx:rmi://127.0.0.1/stub/{base64}
中的 stub
代表 jrmp
協(xié)議,之后的 {base64} 編碼字符串中包含了用于 jrmp
協(xié)議通信的 host 和 port。
至此博烂,可以使用 jrmp
協(xié)議進(jìn)行通信(遠(yuǎn)程方法調(diào)用)