Remote JRCMD for JRockit R28.x

On popular demand, here is how write a remote JRCMD for R28.x:

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 final class RemoteJRCMD {
	private final static String KEY_CREDENTIALS = 
		"jmx.remote.credentials";
	private final static String JROCKIT_PERFCOUNTER_MBEAN_NAME = 
		"oracle.jrockit.management:type=PerfCounters";
	private final static String JROCKIT_CONSOLE_MBEAN_NAME = 
		"oracle.jrockit.management:type=JRockitConsole";
	private final static String[] SIGNATURE = 
		new String[] {"java.lang.String"};
	private final static String DIAGNOSTIC_COMMAND_MBEAN_NAME = 
		"oracle.jrockit.management:type=DiagnosticCommand";

	public static void main(String[] args)
			throws Exception {
		HashMap commandMap = 
			parseArguments(args);
		executeCommand(
				commandMap.get("-host"),
				Integer.parseInt(commandMap.get("-port")),
				commandMap.get("-user"),
				commandMap.get("-password"),
				commandMap.get("-command"));
	}

	private static HashMap parseArguments(
			String[] args) {
		HashMap commandMap = 
			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;
			}
		}
		return commandMap;
	}

	@SuppressWarnings("unchecked")
	public static void executeCommand(
			String host, int port, String user,
			String password, String command)
			throws Exception {
		MBeanServerConnection server = null;
		JMXConnector jmxc = null;
		Map map = 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(
					"oracle.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");
	}
}

(This example can also be found in the JRockit book, at the end of chapter 11.)

The following example would list all the performance counters and their values on the JVM running the RemoteJRCMD itself:

java RemoteJRCMD –port 0

The following example would list all the available commands in a JVM with a management agent open on the default port (7091) on localhost:

java RemoteJRCMD –command help

The following example would print the help on the command “print_threads”, which performs a thread stack dump:

java RemoteJRCMD –command help print_threads

The following example would print a heap histogram per class for the JVM running on port 4711 on the host adastra:

java RemoteJRCMD –port 4711 –host adastra –command print_object_summary

Speaking at Java One and Oracle Develop India!

I will be presenting the following two sessions at Java One in Hyderabad next week:

Thursday, May 3
Time Room Title Abstract Type
17:30-18:20 Hall 5 HotRockit: What to Expect from Oracle’s Converged JVM

Oracle is converging the HotSpot and Oracle JRockit JVMs to produce a “best-of-breed JVM.” Internally, the project is sometimes referred to as the HotRockit project. This presentation discusses what to expect from the converged JVM over the next two years and how this will benefit the Java community.

Conference Session Core Java Platform
         
Friday, May 4
Time Room Title Abstract Type
11:30-13:15 Flexi 1 Production-Time Problem Solving

This tutorial looks at some common problems and pitfalls in Java applications. It focuses on noninvasive profiling and diagnostics of running production systems. Problems tackled:

  • Excessive GC
  • Finding hotspots and optimizing them
  • Optimizing the choice of data structures
  • Synchronization problems
  • Finding out where exceptions are thrown
  • Finding memory leaks

    The presentation demonstrates all problems and solves them, running both the bad-behaving applications and the tools to analyze them from within the Eclipse Java IDE with Oracle JRockit Mission Control Release 4.1.

  • Hands-On Labs

    Looking forward to seeing you there! Ler

    hyderabad

    Speaking at Java One Moscow!

    I will be presenting the following two sessions at Java One in Moscow next week:

    Tuesday, April 17
    Time Room Title Abstract Type
    17:30-18:15 Green Room What’s New in Oracle JRockit Mission Control

    The latest version of JRockit Mission Control is a very potent suite of Java tools for monitoring, managing, profiling, finding latency related problems and hunting for memory leaks in Java applications. This talk will start with a quick re-cap of the major JRockit Mission Control tools, then quickly move on to discuss some exciting features available in the most recently available version of JRockit Mission Control.

    Hands-on Lab
    Java Core Platform
             
    Wednesday, April 18
    Time Room Title Abstract Type
    11:30-13:15 Java One HOL Room Production-Time Problem Solving

    This tutorial looks at some common problems and pitfalls in Java applications. It focuses on noninvasive profiling and diagnostics of running production systems. Problems tackled:

  • Excessive GC
  • Finding hotspots and optimizing them
  • Optimizing the choice of data structures
  • Synchronization problems
  • Finding out where exceptions are thrown
  • Finding memory leaks

    The presentation demonstrates all problems and solves them, running both the bad-behaving applications and the tools to analyze them from within the Eclipse Java IDE with the upcoming Oracle JRockit Mission Control Release 4.1.

  • Hands-On Labs

    Looking forward to seeing you there! Ler

    image

    Mission Control and Time Zones

    Sometimes when you use Mission Control remotely, or when analyzing a Flight Recording from a computer in another time zone, you may want to use the same time zone in the Mission Control client as the remote computer. You may, for instance, have access to logs where the time stamps are in the remote computer’s time zone, and you would want all the time stamps in the Flight Recorder user interface to be in the same time zone. Of course, one way to do this is to change the time zone of the computer running the Mission Control client. However, an easier way is to add the user.timezone parameter to the Mission Control launcher, like this:

    jrmc -J-Duser.timezone=PST

    Substitute PST for the time zone needed, e.g. EST, GMT, CET.

    On some machines you will not be able to use abbreviated time zone names. On such machines, simply use the full time zone name, such as America/Los_Angeles. You can hook up the Mission Control Console to itself to verify that the time zone was properly set:
    JRMC Console

    Speaking at Jfokus!

    I’ve been invited to  present the following session at Jfokus:

    Presentation: What to Expect from HotRockit

    Oracle is converging the HotSpot and Oracle JRockit JVMs to produce a "best-of-breed JVM." Internally, the project is sometimes referred to as the HotRockit project. This presentation discusses what to expect from the converged JVM over the next two years and how this will benefit the Java community.

    My session will take place in A2, at 14:00 on Wednesday the 15th of February. Looking forward to seeing you there!

    Getting Rid of Unwanted Preference Pages in Eclipse

    I recently wanted to get rid of a preference page I did not want to expose in Mission Control (an Eclipse RCP based application), and ended up with the following code in my ApplicationWorkbenchWindowAdvisor:

    private void removeUnwantedPreferencesPages() {
        PreferenceManager pm = PlatformUI.getWorkbench().getPreferenceManager();
        IPreferenceNode root = getRoot(pm);
        removePrefsPage(root, "org.eclipse.equinox.security.ui.category"); //$NON-NLS-1$
    }


    private IPreferenceNode getRoot(PreferenceManager pm) {
        try {
            Method m = PreferenceManager.class.getDeclaredMethod("getRoot", (Class[]) null); //$NON-NLS-1$
            m.setAccessible(true);
            return (IPreferenceNode) m.invoke(pm);
        } catch (Exception e) {
           LoggingToolkit.getLogger().log(Level.WARNING, "Could not get the root node for the preferences, and will not be able to prune unwanted prefs pages.", e); //$NON-NLS-1$
        }
        return null;
    }

    private void removePrefsPage(IPreferenceNode root, String id) {
        for (IPreferenceNode node : root.getSubNodes()) {
            logPrefsNode(node);
            if (node.getId().equals(id)) {
               root.remove(node);
               LoggingToolkit.getLogger().log(Level.INFO, String.format("Removed preference page %s (ID:%s)", node.getLabelText(), node.getId()));   //$NON-NLS-1$
            } else {
               removePrefsPage(node, id);
            }
        }
    }

    If you need to know the ID of the preference page you wish to remove, simply walk the tree and print all the nodes instead of removing selected ones.

    Hope this helps someone. Blinkar

    Could not enumerate processes (1) error?

    With JRockit, you may sometimes see the following warning when starting the JVM (on Windows):

    [WARN ][osal ] Could not enumerate processes (1) error=-1073738819
    [WARN ][osal ] Could not add counter (null)\ for query
    [WARN ][osal ] Failed to init virtual size counter

    It may also look something like this:

    [JRockit] WARNING: Could not initialize the virtualbytes counter, some functionality in jrockit.management.Memory will not be available. Message was: failed to create counter query. String was: (null)\Virtual Bytes

    Or like this:

    [JRockit] WARNING: Could not initialize the JVM process load counter, CPU load generated by the JVM will not be available. Message was: failed to create counter query. String was: (null)\% Processor Time

    This means the JRockit cannot access the relevant PDH counters. Sometimes the counter is disabled, and then it can simply be re-enabled.  Worst case, the counters can be corrupt, and the metadata needs to be rebuilt from system backup store.

    To check the status of the counters, open a command prompt as admin, and run lodctr /q, as follows:

    C:\Windows\system32>lodctr /q
    Performance Counter ID Queries [PERFLIB]:
    Base Index: 0x00000737 (1847)
    Last Counter Text ID: 0x00001572 (5490)
    Last Help Text ID: 0x00001573 (5491)
    [.NET CLR Data] Performance Counters (Enabled)
    DLL Name: netfxperf.dll
    Open Procedure: OpenPerformanceData
    Collect Procedure: CollectPerformanceData
    Close Procedure: ClosePerformanceData
    First Counter ID: 0x00001092 (4242)
    Last Counter ID: 0x0000109E (4254)
    First Help ID: 0x00001093 (4243)
    Last Help ID: 0x0000109F (4255)
    [.NET CLR Networking] Performance Counters (Enabled)
    DLL Name: netfxperf.dll
    Open Procedure: OpenPerformanceData
    Collect Procedure: CollectPerformanceData
    Close Procedure: ClosePerformanceData
    First Counter ID: 0x00001086 (4230)
    Last Counter ID: 0x00001090 (4240)
    First Help ID: 0x00001087 (4231)
    Last Help ID: 0x00001091 (4241)
    [.NET Data Provider for Oracle] Performance Counters (Enabled)
    DLL Name: netfxperf.dll
    Open Procedure: OpenPerformanceData
    Collect Procedure: CollectPerformanceData
    Close Procedure: ClosePerformanceData
    First Counter ID: 0x00001068 (4200)
    Last Counter ID: 0x00001084 (4228)
    First Help ID: 0x00001069 (4201)
    Last Help ID: 0x00001085 (4229)

    If it says (Disabled) next to a provider, the provider can be enabled with:

    C:\Windows\system32>lodctr /e:<provider name> (where <provider name> is the string between the brackets at the beginning of the entry).

    If the performance counters still behave badly, rebuild them from system backup store by running:

    C:\Windows\system32>lodctr /r

    Some counters may still be disabled after this. Use lodctr /q and lodctrl /e as described above to enable the ones you need.

    If lodctrl is not available on your version of Windows, this article may help.