3

I am using Jmeter to do load test using Ant plugin. Currently capturing server's JVM metrics during the test using JFR GUI mode, for each node. It is cumbersome to start for each node and sometimes its getting missed to start. Is there a way to start doing them together via code?

Client details

Hotspot JDK 1.8_131, Mac OS, Jmeter 4.0

Server details

Hotspot 1.8.0_152, OEL , Tomcat

In internet I am getting the options to start JFR programmatically in server node, which will not work for me.

aruma
  • 123
  • 12

1 Answers1

4

If you have terminal access, you could create a script and start a recording using the command line tool jcmd.

$ jcmd <class/jarfile> VM.unlock_commercial_features
$ jcmd <class/jarfile> JFR.start

or

$ jcmd (to list available pids)
$ jcmd <pid> VM.unlock_commercial_features
$ jcmd <pid> JFR.start

For more details, see Example 2-1 Dynamic Interaction Using jcmd

If you can't access the server over SSH, or don't want to do it in the shell, you could use JMX and send the same conmands as diagnostic commands.

In JMC, in the Management/JMX Console you can inspect the MBeans on the server. There you will find the "com.sun.management / DiagnosticCommand" MXBean and the operations which you can write code against. The object name is com.sun.management:type=DiagnosticCommand and you need to call it with jfrStart.

You can set up the connection like this.

String host ="myHost";
int port = 1234;
HashMap map = new HashMap();
String[] credentials = new String[2];
credentials[0] = user;
credentials[1] = password;
map.put("jmx.remote.credentials", credentials);
String s = "/jndi/rmi://" + host + ":" + port + "/jmxrmi";
JMXServiceURL url = new JMXServiceURL("rmi", "", 0, s);
JMXConnector c= JMXConnectorFactory.newJMXConnector(url, map);
c.connect();
MBeanServerConnection conn = c.getMBeanServerConnection();

If you don't care about security, you can set map to null. Then you create an object name and invoke the operation you like to execute, for example:

ObjectName on = new ObjectName("com.sun.management:type=DiagnosticCommand"); 
Object[] args = new Object[] {
    new String[] {
        "dumponexit=true",
        "filename=/recordings/rec.jfr",
        "duration=600s"
    }
};
String[] sig = new String[] {"[Ljava.lang.String;"};
conn.invoke(on, "jfrStart", args, sig);

In JDK 9 and later there is a FlightRecorderMXBean that can be used for remote access (including recording download), but if you are stuck on JDK 8, I would do the above. There is a MBean in Oracle JDK 8 as well, but it is unsupported, undocumented and black magic is needed to make it work.

Kire Haglin
  • 6,569
  • 22
  • 27
  • 1
    Thanks Kire. I have to go with last option (diagnostic commands). Any pointers to sample code from scratch for a beginner like me in working with JMX Mbeans would be helpful? – aruma Apr 19 '19 at 21:01
  • You will have to Google it, but the JMC implementation of invoking diagnostic commands over JMX could be of help. https://github.com/JDKMissionControl/jmc/blob/develop/application/org.openjdk.jmc.rjmx/src/main/java/org/openjdk/jmc/rjmx/services/internal/HotSpot24DiagnosticCommandService.java – Kire Haglin Apr 20 '19 at 01:58