I want to simulate what jconsole
does by:
Identifying a running process that exposes jmx functionality (e.g: pid: 14796 FreshProject.jar
)
Listing the available MBeans libraries (e.g: org.jacoco
)
Invoking an operation (e.g: clicking dump
)
I've tried using the simplejmx
library as mentioned here but I am confused as to what hostName
and port
I should use. I tried passing localhost
and 1099
as I've read these are the default values but it errors java.net.ConnectException: Connection refused: connect
.
Please don't point me to a different sof post and close this as I most probably already read and tried it several times.
I want to simulate what jconsole does
Have a look at the implementation of jconsole - see http://openjdk.java.net/tools/svc/jconsole/ and https://github.com/openjdk/jdk/tree/master/src/jdk.jconsole/share/classes
I am confused as to what hostName and port I should use. I tried passing localhost and 1099 as I've read these are the default values but it errors java.net.ConnectException: Connection refused: connect.
As per https://docs.oracle.com/en/java/javase/11/management/monitoring-and-management-using-jmx-technology.html by default there is no port. And JConsole uses Attach API - see https://github.com/openjdk/jdk/blob/master/src/jdk.jconsole/share/classes/sun/tools/jconsole/LocalVirtualMachine.java In this code you'll also find answer on
Identifying a running process that exposes jmx functionality
To connect via port you need to specify appropriate parameters. For example following Example.java
class Example {
public static void main(String[] args) {
while (true) {
}
}
}
can be started as
java \
-Dcom.sun.management.jmxremote.port=1099 \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=false \
Example
Then
Listing the available MBeans
can be done as
import javax.management.MBeanServer;
import javax.management.MBeanServerConnection;
import javax.management.MBeanServerInvocationHandler;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import java.lang.management.ManagementFactory;
import java.util.Iterator;
import java.util.Set;
class GetMBeans {
public static void main(final String[] args) throws Exception {
final JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi");
final JMXConnector jmxc = JMXConnectorFactory.connect(url, null);
final MBeanServerConnection connection = jmxc.getMBeanServerConnection();
Set<ObjectInstance> instances = connection.queryMBeans(null, null);
Iterator<ObjectInstance> iterator = instances.iterator();
while (iterator.hasNext()) {
ObjectInstance instance = iterator.next();
System.out.println(instance.getClassName() + " " + instance.getObjectName());
}
}
}
After start of the above Example
also with JaCoCo
java \
-Dcom.sun.management.jmxremote.port=1099 \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=false \
-javaagent:jacoco-0.8.4/lib/jacocoagent.jar=jmx=true \
Example
execution of javac GetMBeans.java && java GetMBeans | grep jacoco
produces
org.jacoco.agent.rt.internal_035b120.Agent org.jacoco:type=Runtime
Invoking an operation
is shown in JaCoCo documentation - see MBeanClient.java
at https://www.jacoco.org/jacoco/trunk/doc/api.html
import javax.management.MBeanServer;
import javax.management.MBeanServerConnection;
import javax.management.MBeanServerInvocationHandler;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import java.lang.management.ManagementFactory;
import java.util.Iterator;
import java.util.Set;
class MBeanClient {
public static void main(final String[] args) throws Exception {
final JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi");
final JMXConnector jmxc = JMXConnectorFactory.connect(url, null);
final MBeanServerConnection connection = jmxc.getMBeanServerConnection();
final IProxy proxy = (IProxy) MBeanServerInvocationHandler.newProxyInstance(connection, new ObjectName("org.jacoco:type=Runtime"), IProxy.class, false);
final byte[] data = proxy.getExecutionData(false);
System.out.println("Got " + data.length + " bytes");
}
public interface IProxy {
String getVersion();
String getSessionId();
void setSessionId(String id);
byte[] getExecutionData(boolean reset);
void dump(boolean reset);
void reset();
}
}
execution of javac MBeanClient.java && java MBeanClient
produces
Got 84 bytes