This is an updated version of my JRCMD goes remote blog entry. In version R27 JRockit had a major overhaul of the MBeans used to expose JRockit specific manageability features. One major difference is that the JRockit specific features are not loaded into the platform MBean server by default. To load them, a specific MBean must first be created, which in turn will load the rest of the MBeans exposing the API. The MBeans also moved to a new domain: "bea.jrockit.management".
The MBean to load is the bea.jrockit.management:JRockitConsole MBean. This can be done by simply using the MBeanServerConnection, for example like this:
MBeanServerConnection#createMBean( "bea.jrockit.management.JRockitConsole", null);
The following example is an altered version of my old "JRCMD Goes Remote" blog that, just like the JRCMD, allows the performance counters and ctrl-break handlers to be read/executed - but remotely from another machine.
import java.lang.management.ManagementFactory; import java.net.MalformedURLException; import java.util.HashMap; import java.util.Iterator; import java.util.Map;import javax.management.Attribute;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;/**
* Simple code example on how to execute ctrl-break handlers remotely.
*
* Usage: RemoteJRCMD -host-port -user -pass
* -command[ ]
*
* All arguments are optional. If no command is specified, all performance
* counters and their current values are listed.
*
* @author Marcus Hirt
*/
public class RemoteJRCMD {
private final static String KEY_CREDENTIALS = "jmx.remote.credentials";
private final static String JROCKIT_PERFCOUNTER_MBEAN_NAME = "bea.jrockit.management:type=PerfCounters";
private final static String JROCKIT_CONSOLE_MBEAN_NAME = "bea.jrockit.management:type=JRockitConsole";
private final static String[] SIGNATURE = new String[] { "java.lang.String" };
private final static String DIAGNOSTIC_COMMAND_MBEAN_NAME = "bea.jrockit.management:type=DiagnosticCommand";
public static void main(String[] args) throws Exception {
HashMapcommandMap = new HashMap ();
commandMap.put("-host", "localhost");
commandMap.put("-port", "7091");
for (int i = 0; i < args.length; i++) {
if (args[i].startsWith("-")) {
StringBuilder buf = new StringBuilder();
int j = i + 1;
while (j < args.length && !args[j].startsWith("-")) {
buf.append(" ");
buf.append(args[j++]);
}
commandMap.put(args[i], buf.toString().trim());
i = j - 1;
}
}
executeCommand((String) commandMap.get("-host"), Integer
.parseInt(commandMap.get("-port")), commandMap.get("-user"), commandMap
.get("-password"), commandMap.get("-command"));
}public static void executeCommand(String host, int port, String user,
String password, String command) throws Exception {
MBeanServerConnection server = null;
JMXConnector jmxc = null;
Mapmap = null;
if (user != null || password != null) {
map = new HashMap();
final String[] credentials = new String[2];
credentials[0] = user;
credentials[1] = password;
map.put(KEY_CREDENTIALS, credentials);
}
// Use same convention as Sun. localhost:0 means "VM, monitor thyself!"
if (host.equals("localhost") && port == 0) {
server = ManagementFactory.getPlatformMBeanServer();
} else {
jmxc = JMXConnectorFactory.newJMXConnector(
createConnectionURL(host, port), map);
jmxc.connect();
server = jmxc.getMBeanServerConnection();
}System.out.println("Connected to " + host + ":" + port);
try {
server.getMBeanInfo(new ObjectName(JROCKIT_CONSOLE_MBEAN_NAME));
} catch (InstanceNotFoundException e1) {
server.createMBean("bea.jrockit.management.JRockitConsole", null);
}if (command == null) {
ObjectName perfCounterObjectName = new ObjectName(
JROCKIT_PERFCOUNTER_MBEAN_NAME);
System.out.println("Listing all counters...");
MBeanAttributeInfo[] attributes = server.getMBeanInfo(
perfCounterObjectName).getAttributes();
System.out.println("Counter\tValue\n=======\t====");String[] attributeNames = new String[attributes.length];
for (int i = 0; i < attributes.length; i++) {
attributeNames[i] = attributes[i].getName();
}
Iterator valueIter = server.getAttributes(perfCounterObjectName,
attributeNames).iterator();
while (valueIter.hasNext()) {
Attribute attr = (Attribute) valueIter.next();
System.out.println(attr.getName() + "\t=\t" + attr.getValue());
}
} else {
System.out
.println("Invoking the ctrl-break command '" + command + "'...");
ObjectName consoleObjectName = new ObjectName(DIAGNOSTIC_COMMAND_MBEAN_NAME);
Object[] params = new Object[1];
params[0] = command;
System.out.println("The CtrlBreakCommand returned: \n"
+ server.invoke(consoleObjectName, "execute",
params, SIGNATURE));
}if (jmxc != null) {
jmxc.close();
}
}private static JMXServiceURL createConnectionURL(String host, int port)
throws MalformedURLException {
return new JMXServiceURL("rmi", "", 0, "/jndi/rmi://" + host + ":" + port
+ "/jmxrmi");
}
}
The following example would list all the performance counters and their values on localhost on the default port (7091):
java RemoteJRCMD
The following example would start a 60 second JRA recording on a JRockit running at the host bitsy, port 7099, writing the resulting recording to a file called nisse.zip:
java RemoteJRCMD -command jrarecording filename=nisse time=60 -host bitsy -port 7091
And as always, don't forget to enable the JMX management agent of the JRockit you wish to monitor. You can enable the management agent by using the -Xmanagement option like so:
-Xmanagement:port=7091,ssl=false,authenticate=false