Skip navigation.
Arch2Arch Tab BEA.com

JRockit 1.4 - The JVM at your fingertips

by Marcus Hirt
04/27/2004

The BEA WebLogic JRockit Java Virtual Machine offers more than just a performance advantage. This article discusses some new (experimental) manageability and usability features that are available in the 1.4.2 version of JRockit (Q2 2004). We will briefly look at:

  • The JRockit Management Console headless mode
  • The Ctrl-Break Handler - Interacting with the JVM at runtime
  • The Memory Leak Tool - Hunting memory leaks
  • Code Caching - Drastically lowering startup times
  • Heap View - A picture says more than a thousand datapoints
  • Code Coverage - High performance statement code coverage
  • The JRockit Runtime Analyzer

The JRockit Management Console Headless Mode (Experimental)

The JRockit Management Console is a tool to monitor running JRockits. It consists of two parts: a lightweight server running in the JVM process, and a standalone client with a graphical user interface. The user interface can, among other things, draw graphs of key health indicators of the Java Virtual Machines to which it is connected. Graphics-intensive applications can be very resource hungry, and the JRockit Management Console is no exception. To be able to use the notification functionality and data-collection facilities of the Management Console without incurring the overhead of the GUI, a new text-only mode has been introduced.

With the headless console a number of new command-line parameters were introduced that are also applicable for the GUI version of the console. The arguments are:

Argument Description
-headless Starts the console in the headless mode (won't load GUI related classes).
-settings <settings file> Will startup 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 all connections available in the settings XML file (i.e., previously added using the GUI).
-connect <connection 1> <connection 2> <...> Will connect to the named connections available in the XML settings file using the GUI.
-autoconnect Will automatically connect to any JRockit running the management server with 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 ManagementConsole and then exit.

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 JDP (see below). After 30 seconds it will start issuing ctrlbreaks to all connected JRockits in one-minute intervals . After an hour it will automatically shut down. All notification rules that have been 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 the user initiated actions that are displayed under the Plugins menu in the graphical user interface of the JRockit Management Console. There are two default user actions supplied with the console: the jrarecording user action, which initiates a JRA recording on the connected JRockits and ctrlbreak, which sends ctrl-breaks to the connected JRockits (see 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. The example below demonstrates how to make a User Action that simply retrieves a thread stack dump from all connected JRockits:


 package com.example.useractions;

        import java.util.*;
        import java.util.List;

        import com.jrockit.common.rmp.*;
        import com.jrockit.common.rmp.RmpCommands;
        import com.jrockit.console.connection.ConnectorModel;
        import com.jrockit.console.useractions.AbstractUserAction;

        /**
         * Testaction to request a stackdump from JRockit. 
         * (Just an example; no errorhandling or recovery.)
         * 
         * @author Marcus Hirt
         */
        public class StackDumpAction extends AbstractUserAction {
           /**
            * @see com.jrockit.console.useractions.UserAction#executeAction(List)
            */
           public void executeAction(List connections) {
              if (connections.size() > 0) {
                 Iterator iter = connections.iterator();
                 while (iter.hasNext()) {
                    ConnectorModel cm = (ConnectorModel) iter.next();
                    if (cm.isConnected()) {
                       try {
                          System.out.println(cm.sendQuery(RmpCommands.THREAD_STACK_DUMP));
                       }
                       catch (JRockitConnectionException e) {
                          e.printStackTrace();
                       }
                    }
                 }
              }
           }
        }

Then you need to enter a deployment descriptor in the consolesettings.xml, under the user_actions element:


        <user_action>
                <user_action_class>com.example.useractions.StackDumpAction</user_action_class>
                <user_action_name>mystackdump</user_action_name>
                <user_action_menu_name>My Stack Dump Action</user_action_menu_name>
                <user_action_description>Example. Gets a stackdump from every connected JRockit and
                prints it to stdout.</user_action_description>
        </user_action>
   

This will also make your User Action visible in the user interface under the Plug In menu.

If you have settings/state you need to load/store from the settings file when the console starts/exits, you simply override exportToXml()/importFromXml() like in the following 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 RMP commands docs for more information. Please note that this is experimental functionality; the supplied documentation is rather spartan. Writing custom Notification Actions/Constraints is done in a similar fashion. See the ordinary 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 startup JRockit with the server side of the JDP turned on:


       java -Xmanagement -Djrockit.managementserver.autodiscovery=true <your program>

The Ctrl-Break Handler (Experimental)

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 will first 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 time stamp, 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 which 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. 
        
        # command_line
        #  Prints the command line used to start JRockit. 

        # print_object_summary
        #  See Memory Leak Tool.
 
        # print_class_summary
        #  Prints all loaded classes. 

        # print_utf8pool
        #  Print all UTF8 strings. 

        # gcreport
        #  Prints ASCII graphics representing the heap.

        # jrarecording [filename=<file>] [time=<time>] [nativesamples=true]
        #  Starts a JRA recording.

        # run_optfile [filename=<file>]
        #  See OptFile. 

        # start_management_server
        #  Starts the management server. (Actually the listening socket that in turn starts 
        #  servers whenever a connection is established). 

        # kill_management_server
        #  Stops the management server. (Actually shuts down the listening socket.) The only 
        #  reason it isn't named stop_management_server is that stop is a reserved keyword 
        #  that stops the parsing of the act file. ;) 

        # lockprofile_print
        #  Will print the current values of the lock profile counters. Enable lock profiling
        #  with -Djrockit.lockprofiling. 

        # lockprofile_reset
        #  Will reset the current values of the lock profile counters. Enable lock profiling 
        #  with -Djrockit.lockprofiling. 
 

The Memory Leak Tool (Experimental)

The Memory Leak Tool helps you to, as the name suggests, hunt down memory leaks. It gives you a detailed list of the number of instances of each type, as well as the memory usage by type:


                    --------- Detailed Heap Statistics: ---------
                      51.5%     98k      890    +98k [C
                      15.3%     29k       21    +29k [B
                       8.2%     15k      672    +15k java/lang/String
                       3.9%      7k        1     +7k [S
                       2.2%      4k      178     +4k java/util/HashMap$Entry
                       2.0%      3k       84     +3k [Ljava/util/HashMap$Entry;
                         .        .        .      .     ...
                               191k total ---
                         |        |        |      |      |
    % of live objects ----        |        |      |      |
    size in kilobytes -------------        |      |      |
          # instances ----------------------      |      |
    change in size since last listing -------------      |
                            classname --------------------

It also sports a list of what types that point to a certain instance type. You can, for instance, find out who’s pointing to java.lang.String. You can get 'points to' data for at most three classes in one listing.


 java/lang/String is pointed to from: 
                41.1%   535 java/lang/Class
                15.4%   201 java/util/HashMap$Entry
                9.5%    124 java/util/Hashtable$Entry
 

It can also print all allocation sites, including the whole stack trace, for a specified type. (This functionality must be enabled from command line, as it includes instrumenting generated code.)


 Allocation site: 0 for class java/lang/String
                at java/io/BufferedReader.readLine(BufferedReader.java:331)
                at java/io/BufferedReader.readLine(BufferedReader.java:362)
                at java/util/Properties.load(Properties.java:192)
                at java/util/logging/LogManager.readConfiguration(L:555)
                  .
                at java/lang/Thread.run(Unknown Source)
                --- End of stack trace

        Allocation site: 1 for class java/lang/String
                at java/util/Locale.toUpperCase(Locale.java:1138)
                at java/util/Locale.<init>(Locale.java:265)
                at java/util/Locale.<clinit>(Locale.java:195)
                at java/util/Locale.getDefault(Locale.java:???)
                at java/lang/String.toLowerCase(Unknown Source)
                at java/net/URL.<init>(URL.java:366)
                  .
                at java/lang/Thread.run(Unknown Source)
                --- End of stack trace

There are two different ways of accessing the information:

  1.  Use startup options to let JRockit know what you want to look for and how
  2.  Use the ctrl-break handler and a ctrlhandler.act file to on demand tell the JVM that is running what to look for and how.

The difference between the two options is that the second one is demand driven and you can change that one while the JVM is running, the first one is periodic and cannot be changed while the JVM is running only during startup. However, the first one is the only way of enabling allocation site information so that you can see where a certain type of object is allocated. This can be good for finding out where your leak could be.

Starting MemLeak using startup options

  • -Djrockit.memleak=true - enables detailed heap statistics after GCs
  • -Djrockit.memleak.period=# - informs memleak on how frequent to count and display detailed heap statistics: 1 means every gc, 2 means every other gc etc.
  • -Djrockit.showallocsiteforclass=name - prints the back-trace for each allocation site of the named class. Each back-trace is only printed out the first time it appears, though the same allocation site might be displayed multiple times if the back-trace is different.  

Starting MemLeak using the CtrlBreakHandler

Add the following line to your ctrlhandler.act file:


 
  print_object_summary [name1=<classname>] [name2=<classname>] 
  [name3=<classname>] [cutoff=<number>] [cutoffpointsto=<number>] 
  [increaseonly=true] [inbytes=true]
  • name1 - the 1st class to show 'points to' information about. The class names should have /:s instead of .:s
  • name2 - the 2nd class to show 'points to' information about.
  • name3 - the 3rd class to show 'points to' information about.
  • cutoff - class that represent less than this percentage of total live objects (measure in size) will not be displayed. This can be used for very large systems where you have 1000s of different classes, where you have very few instances of most types. Currently the percentage should be multiplied by 1000 so 1.5% would be 1500
  • cutoffpointsto - like cutoff but for 'points to' information increaseonly set if you only want to display the classes that increased since the last listing. Keep in mind that cutoff is still active and classes that represent less than that %-age of total live objects will not be displayed even though they have increased.
  • inbytes - set to display sizes in bytes instead of the default kilobytes.

Note: When allocation site is enabled you will also see some cryptic information at the end of the deatailed heap statistics dump: "[0: 2] [1: 5]" This is information about what allocation sites are called most frequently. The first number in each pair is the allocation site, the second number is a frequency counter; a high number means that it is called often. The way it works is that every n:th time one of the allocation sites is reached the counter for that allocation site is incremented.

Code Caching (Experimental)

Programs written in a statically compiled language, like c, generally have a shorter startup time than programs written in Java, since they don't need to be translated from byte code into platform-dependent machine code each time they are run. As applications get larger, the startup time becomes more evident and todays large application servers usually take some time to get up and running. The code caching feature of JRockit combines the power of a dynamic language with the load times of a statically compiled language!

Code caching persists generated code on disk, which usually results in greatly reduced startup times. The methods are stored in a single cache file and are appended as they are generated. When a method is regenerated, for instance due to optimization, the new improved version will be stored. An md5 hash is used to detect changes to the class files. 

The cache file depends, of course, on the application, but most of all on the underlying architecture the JRockit is running on. If the machine architecture, operating system or garbage collection strategy has changed from the types used when the cache was generated, the cache will be ignored.

Usage: -XXcodecache[:<option>[=value]][,...]

Commonly used options:

  • file=<filename>
    The file to save to
  • ro | readonly | lo | loadonly
    Only read from the file
  • clob | clobber
    Overwrite the cache file
  • verbose=<level>
    Level of verbosity (1-3)

The most common use case is to start the complete application once with the clobber option, and run through most functionality to create a cache containing code generated for most commonly hit methods. Then shutdown and restart the application using the readonly option. The read only option allows for the cache to be shared among several instances of JRockit.

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 things like fragmentation/compaction and how the algorithm is performing in general. The amount of data in these snapshots is too large to make sense by just inspecting it, so the JRockit team has a small tool that provides a graphical representation that is much easier to interpret.

Here's an example of a snapshot (made using a very early, pre-release version of JRockit 1.4.2):

1

Every row represents a garbage collection. The left side is the beginning of the heap and the right 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 (i.e. filled with objects). Grayish areas are fragmented. It is possible to specify what to display in the configurable graph from the command line. The tool is still very 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 like how much, and exactly what, of the code base that 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 that 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 statement code coverage built in from the very start. When running with code coverage turned on, the code is generated with traps to code that registers the line hit. Once a line has been hit, and recorded, the trap is removed and JRockit can continue to run with 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 behaviour:

System property Description
jrockit.codecoverage.filter=<filterspec> Sets which classes should be covered. Filterstrings starting with "-" will be considered as classes that should not be covered. Separate filters with ";" on windows and ":" on linux
Example:
-Djrockit.codecoverage.filter=java/util/Hashtable;com/bea/*;-com/bea/blabla.*
jrockit.codecoverage.filterfile=<filename> Set the filename of a file containing the filter definition. The fileformat is one filterstring per line.
jrockit.codecoverage.outputfile=<filename> Set the file where output is written. If the output file cannot be opened for writing <filename>_0, <filename>_1
and so on will be tried. This can be useful if several JVMs share a common commandline.
jrockit.codecoverage.testid=<id-string> Set the initial test identifier
jrockit.codecoverage.verbose Make code coverage more verbose. Useful for performing textual diffs between coverage files. Everything plain text.
jrockit.codecoverage.appendoutput Append to the output file rather than overwriting it.

Here are the code coverage specific parameters used when checking the coverage of the management console startup in the example below:


  -Xcodecoverage -Djrockit.codecoverage.filter=com/jrockit/console/*;com/jrockit/common/* 
        -Djrockit.codecoverage.outputfile=console_coverage.txt

Internally we have a small Code Coverage tool that interpret the data generated by JRockit. Here's a screen shot of the tool:

1

 

JRockit Runtime Analyzer (Experimental)

The runtime analyzer is an internal tool to capture and analyze runtime data about JRockit and the application running on JRockit. The tool provides data on a lot of metrics that are of interest for the JRockit developers. Some of these metrics may also be of interest to the JRockit user. Performance wise, the impact of running JRA is slight by design, both to minimize the Heisenberg effect and to make it feasible to use it in a production environment. The JRA provides valuable information that is used to guide the development of JRockit, so if you find that JRockit doesn't provide satisfying performance when running a certain application, you can simply send us a JRA recording of JRockit running your program, and we will use the recorded data to guide future improvements. Send an e-mail to jrockit-improve@bea.com and attach the recording. It would also be helpful if you supplied a few sentences describing the application.

1

For more detailed information on how to use the JRA, see the JRA documentation.

Conclusion

There are a lot of interesting manageability and usability features being developed for the BEA WebLogic JRockit. Many of them will not be ready for primetime until 1.5, but quite a few are already available as technology previews in the upcoming 1.4.2 release of JRockit. If any of the discussed technologies seem interesting to you, please try them out and provide us with feedback. This is a great opportunity for you to influence the way these features work, so that they provide the most value for you once they are released.

Article Tools

Email E-mail
Print Print
Blog Blog

Related Products

Check out the products mentioned in this article:

Bookmark Article

del.icio.us del.icio.us
Digg Digg
DZone DZone
Furl Furl
Reddit Reddit