JRockit 5.0 - The JVM at Your Fingertips


Abstract

The BEA JRockit Java virtual machine (JVM) offers more than just a performance advantage. This article discusses some manageability and usability features available in the 5.0 R26 version of JRockit. In particular, it provides a brief look at the JRockit Mission Control suite of analysis tools, the experimental headless mode for the JRockit Management Console, interacting with the JVM using the Ctrl-Break Handler, JRCMD, Heap View, and code coverage.

Introduction

The JRockit JVM is not only fast, but it also comes with JRockit Mission Control, a suite of analysis tools for performing runtime analysis and memory leak detection. The JRockit Management Console is included with the JRockit JDK. In this article I discuss an experimental headless mode for the JRockit Management Console that can be used for interfacing with JRockit JMX-based management agents from the command line. The Ctrl-Break Handler provides a means to send a variety of advanced commands to JRockit even after it has started. These commands can even be invoked remotely, as I show later in the article. I conclude with a discussion of the experimental code coverage that JRockit provides right out of the box.

For more information on BEA JRockit, stay tuned to the JRockit Product Center on dev2dev.

I'll begin with a quick overview of the established manageability tools available for the JRockit JVM, and then I'll move on to less documented and experimental manageability features.

JRockit Mission Control

The JRockit Mission Control tool suite was introduced with the JRockit R26.0.0 release, and includes tools to monitor, manage, profile, and eliminate memory leaks in your Java applications without introducing the performance overhead normally associated with tools of this type. Mission Control's low performance overhead is a result of using data collected as part of JRockit's normal adaptive dynamic optimization. This also eliminates the problem with the Heisenberg anomaly that can occur when tools using byte code instrumentation alter the execution characteristics of the system. JRockit Mission Control functionality can always be available on demand, and the small performance overhead is only in effect while a tool is running. These properties make the JRockit Mission Control tools uniquely positioned to be used on systems running in production.

The following tools are included in JRockit Mission Control:

  • The JRockit Management Console
    The JRockit Management Console is used to monitor and manage multiple JRockit instances. It captures and presents live data about garbage collector (GC) pauses, memory, and CPU usage, as well as information from any JMX MBean deployed in the JVM internal MBean server. JVM management includes dynamic control over CPU affinity, garbage collection strategy, and memory pool sizes.

  • The JRockit Runtime Analyzer
    The JRockit Runtime Analyzer (JRA) is an on-demand "flight recorder" that produces detailed recordings of the JVM and the application it is running. The recorded profile can later be analyzed offline, using the JRA application. Recorded data includes profiling of methods and locks, as well as garbage collection statistics, optimization decisions, and object statistics.

  • The JRockit Memory Leak Detector
    The JRockit Memory Leak Detector is a tool for discovering and finding the cause of memory leaks. The Memory Leak Detector's trend analyzer can discover very slow leaks; it shows you detailed heap statistics, including referring types and instances to leaking objects and allocation sites, and provides quick drill-down to the cause of the leak. The Memory Leak Detector uses advanced graphical presentation techniques to make it easier to navigate and understand the sometimes complex information.

For more information about JRockit Mission Control, read the article An Introduction to JRockit Mission Control, or visit the JRockit Mission Control page on dev2dev.

The JRockit Management Console Headless Mode (Experimental)

The JRockit Management Console is a tool to monitor running JRockits. It consists of two parts: a JMX agent running in the JVM process, and a standalone client with a graphical user interface (see An Introduction to JRockit Mission Control for further details on this and other aspects). The user interface can, among other things, draw graphs of any numerical attribute of any MBean deployed in the Java virtual machines it is connected to. Graphic-intensive applications can be very resource hungry, and the JRockit Management Console is no exception. A text-only mode has been introduced so you can use the notification functionality and data collection facilities of the Management Console without incurring the overhead of the GUI.

With the headless console a number of new command-line parameters have been introduced. These are also applicable to the GUI version of the console. The arguments are:

Argument Description
-headless Starts the console in the headless mode (will not load GUI-related classes).
-settings <settings file> Will start up using the specified settings file. If starting in GUI mode, and this file doesn't exist, it will be created when closing the Management Console.
-connectall Will connect to all connections available in the settings file (that is, previously added using the GUI).
-connect <connection 1> <connection 2> <...> Will connect to the named connections available in the settings file using the GUI.
-autoconnect Will automatically connect to any JRockit running the management server with JRockit Discovery Protocol (JDP) turned on.
-uptime <time in seconds> Will run the console for the specified amount of time and then automatically shut it down.
-useraction <name> <delay in seconds> <period (optional)> Will run the named user action after the specified delay. If no period has been specified, the action will be run once. If the period has been specified, it will be run every <period> seconds.
-version Will print the version of the Management Console and then exit.
-locale <language> <country (optional)> Will start the console using a certain locale; for example, -locale ja JP, will start the console in Japanese (available with JRockit R27).

Here is an example that will start the management console in headless mode, read the specified settings file, try to connect to all previously specified JRockits, and actively search for new ones using JRockit Discovery Protocol (or JDP, as discussed below). After 30 seconds it will start issuing Ctrl-Breaks to all connected JRockits in one-minute intervals. After an hour it will automatically shut down. All notification rules that were previously added to specific connections, either by using the GUI or directly editing the settings file, will be active.

java -jar ManagementConsole.jar -headless 

   -settings C:\Headless\consolesettings.xml -connectall 

   -autoconnect -uptime 3600 -useraction ctrlbreak 30 60

User actions are plug-in classes that can interact with a set of connections in the JRockit Management Console, and also use the console settings file to store configuration data. The user actions are displayed under the Plugins menu in the graphical user interface of the JRockit Management Console, and are also available from the headless mode. Two default user actions are supplied with the console: the jrarecording user action, which initiates a JRA recording on the connected JRockits; and the ctrlbreak user action, which sends Ctrl-Breaks to the connected JRockits (see the section in this article on Ctrl-Break Handler and The JRockit Runtime Analyzer). The parameters specific to a certain user action can be configured either by using the GUI or by editing the Management Console settings file, which can be found under <user.home>/ManagementConsole/ManagementConsole/consolesettings.<version>.xml.

Writing your own user action is quite easy. First, you create a subclass of AbstractUserAction. This example demonstrates how to make a user action that simply retrieves a thread stack dump from all connected JRockits:

package com.example.useractions;

import java.io.IOException;

import java.util.List;

import com.jrockit.console.rjmx.CommonRJMXNames;

import com.jrockit.console.rjmx.RJMXConnectorModel;

import com.jrockit.console.useractions.AbstractUserAction;



/**

 * This is a simple user action, getting stackdumps from 

 * the selected JRockits and printing them on stdout.

 * 

 * @author Marcus Hirt

 */



public class MyUserAction extends AbstractUserAction

{

  public void executeAction(List<RJMXConnectorModel> connections)

  {

    for (RJMXConnectorModel connection : connections)

    {

      if (connection.isConnected())

      {

        try

        {

          System.out.println(CommonRJMXNames.getThreadMXBean(connection).getThreadStackDump());

        }

        catch (IOException e)

        {          

          e.printStackTrace();

        }

      }

    }

  }

}

Next, you need to enter a deployment descriptor in the consolesettings.xml file to make the user action available to the console. In the settings file you will find a user_actions element; it is already populated with a few user_action elements. The deployment descriptor for our example action should be entered in the same fashion. This is what the descriptor should look like:

<user_action>

  <user_action_class>com.example.useractions.MyUserAction</user_action_class>

  <user_action_name>stackdump</user_action_name>

  <user_action_menu_name>Stack Dump on stdout</user_action_menu_name>

  <user_action_description>Gets a stack dump from the selected JRockit(s), and dumps it on stdout.</user_action_description>

</user_action>

This will also make your user action visible in the user interface under the Plugins menu.

If you have settings/state you need to load/store from the settings file when the console starts or exits, you can simply override exportToXml()/importFromXml(), as shown in this example:

/**

 * @see com.jrockit.console.util.XmlEnabled

 * #exportToXml(org.w3c.dom.Element)

 */



public void exportToXml(Element parentNode)

{

  super.exportToXml(parentNode);

  XmlToolkit.setSetting(parentNode, MY_PROPERTY, m_myVal);

}

/**

 * @see com.jrockit.console.util.XmlEnabled

 * #initializeFromXml(org.w3c.dom.Element)

 */

 

 public void initializeFromXml(Element parentNode) 

 {

   super.initializeFromXml(parentNode);

   m_myVal = XmlToolkit.getSetting(parentNode,

     MY_PROPERTY, DEFAULT_MY_VALUE));

}

Note that the user action name is the name by which you will refer to the user action when using the launcher startup parameters. The menu name is the name that will be displayed in the GUI menu. See the user action docs and the JLMEXT docs for more information. Note that this is experimental functionality; the supplied documentation is rather spartan. Writing custom notification actions and constraints is done in a similar fashion. See the Management Console User Guide for more information.

JRockit Discovery Protocol (JDP)

JDP (JRockit Discovery Protocol) is a simple and efficient protocol for letting the JRockit Management Server multicast its presence to the Management Console. The system properties in the two tables below control the behavior of the JDP for the server and the client, respectively.

Management Server JDP properties

System property Description Default
jrockit.managementserver.autodiscovery Enables the JRockit Discovery Protocol False
jrockit.managementserver.discovery.period How long to wait between pings (in ms) 5000
jrockit.managementserver.discovery.ttl Number of hops to live 1
jrockit.managementserver.discovery.address Multicast address to use 232.192.1.212
jrockit.managementserver.discovery.port Multicast port to use Default is 7095

Management Console JDP properties

System property Description Default
com.jrockit.console.preferences.jdp.port Port to use for the JRockit Discovery Protocol 7095
com.jrockit.console.preferences.jdp.address Multicast address to use 232.192.1.212

Here is an example of the minimum number of parameters needed to start up JRockit with the server side of the JDP turned on:

java -Xmanagement -Djrockit.managementserver.autodiscovery=true

<your program>

The Ctrl-Break Handler

Have you ever wished for an easy way of communicating with the JVM after it has been started? Let's say you forgot to add the -Xmanagement option to start up the management server, or you'd like to change the verbosity level for the GC on a running system. Such things are now easily accomplished by reconfiguring the Ctrl-Break Handler to do much more than just printing stack traces.

Usage

  • Create a file named ctrlhandler.act.
  • Add commands (see the commands box below) to the ctrlhandler.act file.
  • End the file with "stop," which is a reserved command that ends the parsing of the file.
  • When ctrl-break is pressed, each command will be processed in the order of appearance.

JRockit first will search for the file in the current working directory. If the file isn't found, JRockit will look in the directory of the JVM. If the file isn't found there, JRockit will fall back to generating a normal thread stack dump. JRockit will read the act file each time ctrl-break is pressed, so you can reconfigure the file at your leisure while JRockit is still running.

Here is an example act file that first prints a timestamp, then the command line used to start JRockit, and finally a thread stack dump. It also contains a list of useful commands you can use in your act file:

# Example ctrlhandler.act file

timestamp

command_line

print_threads

stop



# set_filename filename=<file> [append=true]

#  Sets the file that all handlers following this command will

#  use for printing. You can have several set_filename commands

#  in a file. It takes two arguments:  filename and an optional

#  append to specify if you want to append to the file 

#  or overwrite it. Default is to overwrite the file. 



# timestamp

#  Prints a timestamp. 



# print_threads

#  The normal thread dump.



# verbosity [args=<components>] [filename=<file>]

#  Changes the verbosity level normally specified with -Xverbose. 



# version

#  Prints JRockit version information. 



# command_line

#  Prints the command line used to start JRockit. 

#  print_object_summary

#  Prints heap usage statistics (how much heap is used per class),

#  together with a delta on how much this has changed since

#  the last invocation of this ctrl-break handler.



# print_memusage

#  Prints a memory usage report of how JRockit is using

#  the memory.



# heap_diagnostics

#  Prints a detailed report of the heap, including ascii graphics 

#  over the heap layout.



# print_class_summary

#  Prints all loaded classes. 



# print_utf8pool

#  Print all UTF8 strings. 



# jrarecording [filename=<file>] [time=<time>] [nativesamples=true]

#  Starts a JRA recording.



# run_optfile [filename=<file>]

#  See OptFile. 



# start_management_server

#  Starts the new JMX-based management agent. 



# kill_management_server

#  Stops the management agent. 



# start_rmp_server

#  Starts the old management server (actually the listening 

#  socket that in turn starts servers whenever a connection

#  is established). 



# kill_rmp_server

#  Stops the old management server (actually shuts down the

#  listening socket). The only reason it isn't named 

#  kill_rmp_server is that stop is a reserved keyword 

#  that stops the parsing of the act file. ;) 



# help [ctrl-break handler]

#  Prints all available ctrl-break handlers if no argument 

#  is specified, or help for the specified ctrl-break handler.



# memleakserver [port=<port>]

#  Toggles the memleakserver. If it hasn't been started 

#  it will be started. If it has already started, it will be

#  shut down. The default port is 7095.



# verbose_referents action=[heap|full|nursery|start|stop]

#  Print verbose reference information.

#  Parameters:

#   action=[heap|full|nursery|start|stop]

#    heap    - trigger a heap collection and output reference

#              information

#    full    - trigger a full heap collection (clears softly 

#              reached soft referents)

#    nursery - trigger a nursery collection (heap collection 

#              if running without nursery)

#    start   - start writing reference information to default

#              verbose stream

#    stop    - stop writing reference information



# print_exceptions 

#  exceptions=[true|all|false] stacktraces=[true|all|false]

#  Enable printing of Java exceptions thrown in the VM.

#  Parameters:

#    exceptions    - print exceptions

#    stacktraces   - print exceptions with stacktraces

#  At least one of the parameters is required.

#  Values for the parameters can be "true|all|false"

#    true  - print all exceptions 

#             except java/util/EmptyStackException,

#             java/lang/ClassNotFoundException and 

#             java/security/PrivilegedActionException

#    all   - print all exceptions

#    false - don't print exceptions

#  To turn exception printing off completely you need to set

#   exceptions = false even if it was turned 

#   on by stacktraces = true.

JRCMD

A new convenient way of invoking the Ctrl-Break Handler is to use the JRCMD utility, available in the bin directory of the JRockit distribution.

Usage

jrcmd <PID> <command> <parameters>
  • PID = The process ID of the JRockit process on which you wish to execute the Ctrl-Break Handler.
  • command = The Ctrl-Break Handler command to execute.
  • parameters = The parameters of the Ctrl-Break Handler.

If no options are specified (or only -p), the process IDs of all JRockits running on the local machine will be shown, together with the startup parameters used to launch the process. If the PID is set to 0, the command will be sent to all the running JRockit JVMs on the local machine.

To list what Ctrl-Break Handlers are available in a certain JRockit, you can use the help command:

jrcmd <PID> help

To get help on a specific Ctrl-Break Handler, just add the name of the Ctrl-Break Handler you need help on, for example:

jrcmd 0 help kill_management_server

You can also use JRCMD to list the performance counters of a specified process:

jrcmd <PID> -l

Invoking Ctrl-Break Handlers Remotely

You can use the JRockit Management Console to invoke Ctrl-Break Handlers remotely. There is an operation on the JRockitConsoleMBean, named runCtrlBreakHandlerWithResult. The JRockit Management Console can invoke operations on MBeans from the attribute browser. Here is a step-by-step description of how to invoke the Ctrl-Break Handler:

  1. Connect to a running JRockit.
  2. Right-click on the connection, and select Browse Attributes.
  3. Expand the com.jrockit domain folder, and select the JRockitConsole MBean.
  4. Click on the operations tab to see the available operations.
  5. Click on the String parameter argument button for the runCtrlBreakHandlerWithResult operation.
  6. Type in the name of the Ctrl-Break Handler you wish to execute. The syntax is the same as for the ctrlhandler.act file. Press OK.
  7. Press the Execute button to execute the operation.

Try entering "help" as the parameter. This will list all available Ctrl-Break Handlers, as shown in Figure 1.

Figure 1
Figure 1. Invoking a Ctrl-Break Handler from the JRockit Management Console (click the image for a full-size screen shot)

Heap View (Experimental)

When analyzing how your application performs with a certain garbage collection strategy, it can be very helpful to get a snapshot of the heap after every GC. This helps developers study data such as fragmentation/compaction and how the algorithm is performing in general. The amount of data in these snapshots is too large to make sense of by just inspecting it, so the JRockit team has a small tool that provides a graphical representation that is much easier to interpret.

Figure 2 shows an example of a snapshot (made using a very early, pre-release version of JRockit 1.4.2):

Figure 2
Figure 2. A sample heap view snapshot (click the image for a full-size screen shot)

Every row represents a garbage collection. The left side is the beginning of the heap, and the right side is the end. On the right side of the heap display is a configurable graph. Solid white areas represent free heap, and black areas are well-compacted areas (that is, areas filled with objects). Grayish areas are fragmented. The red, yellow, and green area is the configurable graph. It is possible to specify what to display in the configurable graph from the command line. The tool is still rough and not very user friendly, and there are doubts as to how useful it is for end users of JRockit, so this is a tool that may very well never reach general availability.

Code Coverage (Experimental)

Many developers use code coverage analysis to study things such as how much, and exactly what part, of the code base is being run when they use their application in a certain way. Testers like using code coverage as a measure of how much of an application is covered by their test suites. For large applications, though, the performance cost incurred by the code coverage tool is often prohibitive.

JRockit has high-performance line code coverage built in. When running with code coverage turned on, the code is generated with traps that register the line hit. Once a line has been hit, and recorded, the trap is removed and JRockit can continue to run at almost full speed.

To make JRockit record code coverage data you must specify a command-line option.

Usage

-Xcodecoverage

You use the following system properties to control the behavior:

System property Description

jrockit.codecoverage.filter=
<filterspec>

The filterspec is a semi-colon- (Windows), or colon (Linux)-separated list of filter strings, which defines what classes should be covered. Filter strings starting with "-" will be considered as classes that should not be covered.

Example:
-Djrockit.codecoverage.filter=
java/util/Hashtable;com/bea/*;-com/bea/bla.*

jrockit.codecoverage.filterfile=
<filename>

Sets the filename of a file containing the filter definition. The file format is one filter string per line.

jrockit.codecoverage.outputfile=
<filename>

Sets the file where output is written. If the output file cannot be opened for writing <filename>_0, then <filename>_1, and so on, will be tried. This can be useful if several JVMs share a common command line.

jrockit.codecoverage.testid=
<id-string>

Sets the initial test identifier.

jrockit.codecoverage.verbose

Makes code coverage more verbose. Useful for performing textual diffs between coverage files. Everything plain text.

jrockit.codecoverage.appendoutput

Sets writing to append to the output file rather than overwriting it.

Here are the code coverage-specific parameters that were used to generate the data shown in the picture below:

-Xcodecoverage -Djrockit.codecoverage.filter=

     com/jrockit/console/*;com/jrockit/common/* 

     -Djrockit.codecoverage.outputfile=console_coverage.txt

Internally, a small code coverage tool interprets the data generated by JRockit, as illustrated in Figure 3.

Figure 3
Figure 3. Sample output from the code coverage tool (click the image for a full-size screen shot)

Conclusion

Being in control of the Java runtime puts BEA in a unique position to deliver low-overhead management and monitoring features for the Java platform. Many interesting manageability and usability features are being developed for BEA JRockit. A few of them became available with JRockit Mission Control, included with JRockit 5.0 R26, and more are just around the corner. For additional information, see the Mission Control home page.

Marcus Hirt is one of the founders of Appeal Virtual Machines, the company that created the Java Virtual Machine JRockit. He is currently working as Engineering Manager for the JRockit Mission Control team.