简体   繁体   中英

How to connect to JMX for JVM on local machine by pid (Java 9+)

I want to query an MBean on a JVM running on the local machine.

String address = "???";
JMXConnectorFactory.connect(new JMXServiceURL(address))
  .getMBeanServerConnection()
  .getAttribute(new ObjectName("<object name>"), "<attribute name>");

I have not set up com.sun.management.jmxremote.port=XXX, but since the jconsole GUI is still able to connect to a JVM and observe/interact with the MBeans there (I've tested this), I assume it's possible to craft an address string that references a JVM process running on a particular pid (since no jmxremote.port=XXX will exist).

However, I can find no documentation on how to construct an address for a local JVM process with a specified pid.

There are some answers from 5+ years ago that use the sun.management.ConnectorAddressLink class, but this class has been removed in Java 9+. I've also tried looking through the source code of several projects such as jmxlocal , but all of these projects are now out of date, and also use that same ConnectorAddressLink class which is now unavailable.

(I presume you are not inquiring about the format of the string, just about how to find the port.)

You could agree on some contract for jmx port(s). If you were to have 2+ jvms on the localhost, they obviously would have distinct ports so the jmx client can't just guess nor port scan (bad etiquette). Maybe a port range to blindly try to connect to.

You could rely on something else, like a broadcast packet, or multicast channel convention to request your programs to reveal they exist on some jmx port, but that you would have to program yourself and expect the jvms to start such module.

Otherwise, on linux by browsing /proc/... you might discover processes (filtering only java ones) and which port they have opened, or some runtime exec backflips with netstat (linux or windows) you might be able to list listening sockets. But again, that doesn't mean these sockets are JMX service - you still need a convention unless you want to probe and hassle the processes arbitrary ports.

However, if you can list processes, you probably can obtain their command lines and find java ones, and their own jmx system properties revealing the port they use...

Few things to try. Hope this helps.

full sample source code: https://github.com/banv-dev/DemoDumpHeap/blob/master/src/main/java/org/example/Main.java

//attach to VM with pid
VirtualMachine vm = VirtualMachine.attach("pid");
//Starts the local JMX management agent in the target virtual machine.
String jmxUrl = vm.startLocalManagementAgent()

//connect via JMX
JMXServiceURL url = new JMXServiceURL(jmxUrl);
JMXConnector connector = JMXConnectorFactory.connect(url);
MBeanServerConnection beanServerConnection = connector.getMBeanServerConnection();

reference: https://docs.oracle.com/en/java/javase/11/docs/api/jdk.attach/com/sun/tools/attach/VirtualMachine.html

https://docs.oracle.com/en/java/javase/11/management/monitoring-and-management-using-jmx-technology.html#GUID-805517EC-2D33-4D61-81D8-4D0FA770D1B8

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM