Cool New Features in JDK7 update 4!

JDK7 was quite recently released, and I thought I should mention a few new cool things in it.

JCMD

First out is the port of the small JRockit command line utility JRCMD (JRockit Command). JRCMD was a command line tool to enumerate the Java processes running on the local machine, and to send commands (referred to as “Diagnostic Commands”) to them. JRCMD has been renamed JCMD (Java Command).

To list the locally running JVMs, simply run JAVA_HOME\bin\jcmd:

C:\Java\JDKs\JDK7_u4_official\bin>.\jcmd
4636 sun.tools.jconsole.JConsole
2620 HotspotKeepAlive
1076 sun.tools.jcmd.JCmd

You will see the JVMs running on the local machine listed by PID followed by main class. To see the commands available, run the help command, like this:

C:\Java\JDKs\JDK7_u4_official\bin>.\jcmd 4636 help
4636:
The following commands are available:
VM.commercial_features
ManagementAgent.stop
ManagementAgent.start_local
ManagementAgent.start
Thread.print
GC.class_histogram
GC.heap_dump
GC.run_finalization
GC.run
VM.uptime
VM.flags
VM.system_properties
VM.command_line
VM.version
help

For more information about a specific command use ‘help <command>’.

To get information about a specific command, use the help command followed by the command name:

C:\Java\JDKs\JDK7_u4_official\bin>.\jcmd 4636 help Thread.print
4636:
Thread.print
Print all threads with stacktraces.

Impact: Medium: Depends on the number of threads.

Syntax : Thread.print [options]

Options: (options must be specified using the <key> or <key>=<value> syntax)
        -l : [optional] print java.util.concurrent locks (BOOLEAN, false)

To get a thread stack dump with the concurrent locks:

C:\Java\JDKs\JDK7_u4_official\bin>.\jcmd 4636 Thread.print -l
4636:
2012-04-27 11:21:57
Full thread dump Java HotSpot(TM) Client VM (23.0-b21 mixed mode, sharing):

"DestroyJavaVM" prio=6 tid=0x003fb000 nid=0xc5c waiting on condition [0x00000000
]
   java.lang.Thread.State: RUNNABLE

   Locked ownable synchronizers:
        – None

"AWT-EventQueue-0" prio=6 tid=0x03e65800 nid=0x128c waiting on condition [0x041c
f000]
   java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        – parking to wait for  <0x2926dce8> (a java.util.concurrent.locks.Abstra
ctQueuedSynchronizer$ConditionObject)
        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject
.await(AbstractQueuedSynchronizer.java:2043)
        at java.awt.EventQueue.getNextEvent(EventQueue.java:511)
        at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThre
ad.java:213)
        at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.
java:163)
        at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThre
ad.java:151)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:147)

        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:139)

        at java.awt.EventDispatchThread.run(EventDispatchThread.java:97)

   Locked ownable synchronizers:
        – None

"Thread-2" prio=6 tid=0x03e61c00 nid=0xd4c in Object.wait() [0x042bf000]
   java.lang.Thread.State: TIMED_WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        – waiting on <0x292432b0> (a java.io.PipedInputStream)
        at java.io.PipedInputStream.read(PipedInputStream.java:327)
        – locked <0x292432b0> (a java.io.PipedInputStream)
        at java.io.PipedInputStream.read(PipedInputStream.java:378)
        – locked <0x292432b0> (a java.io.PipedInputStream)
        at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:283)
        at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:325)
        at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:177)
        – locked <0x29249358> (a java.io.InputStreamReader)
        at java.io.InputStreamReader.read(InputStreamReader.java:184)
        at java.io.BufferedReader.fill(BufferedReader.java:154)
        at java.io.BufferedReader.readLine(BufferedReader.java:317)
        – locked <0x29249358> (a java.io.InputStreamReader)
        at java.io.BufferedReader.readLine(BufferedReader.java:382)
        at sun.tools.jconsole.OutputViewer$PipeListener.run(OutputViewer.java:10
9)

   Locked ownable synchronizers:
        – None

.

.

.
JNI global references: 528

Java Flight Recorder

The second big feature is the first port of the JRockit Flight Recorder – a high performance event recorder built into the JVM. Think of it as the data flight recorder (black box) of an aircraft. It records information about the JVM, its environment and the application running in the JVM, so that, if something happens, clues about what caused the problem can be found. Now, the first port of the flight recorder is quite limited in terms of the events actually being recorded. It is really released to be used with the event producer built into WebLogic Server through WLDF. Also, the Mission Control client is not yet released as part of the JDK (since it is not that useful without WLDF yet). If you’re an Oracle WebLogic customer, you can download the client on MOS.

That being said, to enable the functionality in 7u4, you need to add the following command line flags to your JVM startup command:

JAVA_HOME\bin\java -XX:+UnlockCommercialFeatures -XX:+FlightRecorder <your main class and params>

You can see that it has been enabled by using JCMD. A few flight recorder specific commands should now be available:

C:\Java\JDKs\JDK7_u4_official\bin>.\jcmd 2620 help
2620:
The following commands are available:
JFR.stop
JFR.start
JFR.dump
JFR.check
VM.commercial_features
ManagementAgent.stop
ManagementAgent.start_local
ManagementAgent.start
Thread.print
GC.class_histogram
GC.heap_dump
GC.run_finalization
GC.run
VM.uptime
VM.flags
VM.system_properties
VM.command_line
VM.version
help

For more information about a specific command use ‘help <command>’.

Unless you are a WLS user, I’d personally recommend waiting a release or two before starting using the Flight Recorder. There are not that many OS/JVM/JDK level events available yet, and there is a major performance improvement related to the time stamping of events just around the corner.

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