16 Monitoring, Tuning, and Troubleshooting the JVM

This chapter describes how to monitor and tune Java Virtual Machine (JVM) performance for Oracle Communications Converged Application Server engine servers.

Profiling JVM Performance

Java Flight Recorder and Java Mission Control together create a complete tool chain to continuously collect low level and detailed runtime information enabling after-the-fact incident analysis.

  • Java Flight Recorder is a profiling and event collection framework built into the Oracle JDK that lets Converged Application Server administrators and developers to gather detailed low level information about how the Java Virtual Machine (JVM) and the Java application are behaving.

  • Java Mission Control is an advanced set of tools that enables efficient and detailed analysis of the extensive of data collected by Java Flight Recorder. The tool chain enables developers and administrators to collect and analyze data from Java applications running locally or deployed in production environments.

  • The jcmd utility is used to send diagnostic command requests to the JVM. It must be used on the same machine on which the JVM is running, and have the same effective user and group identifiers that were used to launch the JVM.

Using Java Flight Recorder

You can run multiple recordings concurrently and configure each recording using different settings; in particular, you can configure different recordings to capture different sets of events. However, in order to make the internal logic of Java Flight Recorder as streamlined as possible, the resulting recording always contains the union of all events for all recordings active at that time. This means that if more than one recording is running, you might end up with more information in the recording than you wanted. This can be confusing but has no other negative implications.

The easiest and most intuitive way to use JFR is through the Flight Recorder plug-in that is integrated into Java Mission Control. This plug-in enables access to JFR functionality through an intuitive GUI. For more information about using the JMC client to control JFR, see the Flight Recorder Plug-in section of the Java Mission Control help.

Using the Command Line

You can start and configure a recording from the command line using the -XX:StartFlightRecording option of the java command, when starting the application. To enable the use of JFR, specify the -XX:+FlightRecorder option. Because JFR is a commercial feature, you also have to specify the -XX:+UnlockCommercialFeatures option. The following example illustrates how to run the MyApp application and immediately start a 60-second recording which will be saved to a file named myrecording.jfr:

java -XX:+UnlockCommercialFeatures -XX:+FlightRecorder -XX:StartFlightRecording=duration=60s,filename=myrecording.jfr MyApp

To configure JFR, you can use the -XX:FlightRecorderOptions option.

Using Diagnostic Command

You can also control recordings by using Java-specific diagnostic commands.

The simplest way to execute a diagnostic command is to use the jcmd tool (located in the Java installation directory). To issue a command, you have to pass the process identifier of the JVM (or the name of the main class) and the actual command as arguments to jcmd. For example, to start a 60-second recording on the running Java process with the identifier 5368 and save it to myrecording.jfr in the current directory, use the following:

jcmd 5368 JFR.start duration=60s filename=myrecording.jfr

To see a list of all running Java processes, run the jcmd command without any arguments. To see a complete list of commands available to a running Java application, specify help as the diagnostic command after the process identifier (or the name of the main class). The commands relevant to Java Flight Recorder are:

  • JFR.start

    Start a recording.

  • JFR.check

    Check the status of all recordings running for the specified process, including the recording identification number, file name, duration, and so on.

  • JFR.stop

    Stop a recording with a specific identification number (by default, recording 1 is stopped).

  • JFR.dump

    Dump the data collected so far by the recording with a specific identification number (by default, data from recording 1 is dumped).

Note:

These commands are available only if the Java application was started with the Java Flight Recorder enabled, that is, using the following options:
-XX:+UnlockCommercialFeatures -XX:+FlightRecorder

Configuring Recordings

You can configure an explicit recording in a number of other ways. These techniques work the same regardless of how you start a recording (that is, either by using the command-line approach or by using diagnostic commands).

Setting Maximum Size and Age

You can configure an explicit recording to have a maximum size or age by using the following parameters:

  • maxsize=size
    

    Append the letter k or K to indicate kilobytes, m or M to indicate megabytes, g or G to indicate gigabytes, or do not specify any suffix to set the size in bytes.

  • maxage=age
    

    Append the letter s to indicate seconds, m to indicate minutes, h to indicate hours, or d to indicate days.

If both a size limit and an age are specified, the data is deleted when either limit is reached.

Setting the Delay

When scheduling a recording. you might want to add a delay before the recording is actually started; for example, when running from the command line, you might want the application to boot or reach a steady state before starting the recording. To achieve this, use the delay parameter:

delay=delay

Append the letter s to indicate seconds, m to indicate minutes, h to indicate hours, or d to indicate days.

Setting Compression

Although the recording file format is very compact, you can compress it further by adding it to a ZIP archive. To enable compression, use the following parameter:

compress=true

Note that CPU resources are required for the compression, which can negatively impact performance.

Creating Recordings Automatically

When running with a default recording you can configure Java Flight Recorder to automatically save the current in-memory recording data to a file whenever certain conditions occur. If a disk repository is used, the current information in the disk repository will also be included.

Creating a Recording On Exit

To save the recording data to the specified path every time the JVM exits, start your application with the following option:

-XX:FlightRecorderOptions=defaultrecording=true,dumponexit=true,dumponexitpath=path

Set path to the location where the recording should be saved. If you specify a directory, a file with the date and time as the name is created in that directory. If you specify a file name, that name is used. If you do not specify a path, the recording will be saved in the current directory.

Creating a Recording Using Triggers

You can use the Console in Java Mission Control to set triggers. A trigger is a rule that executes an action whenever a condition specified by the rule is true. For example, you can create a rule that triggers a flight recording to commence whenever the heap size exceeds 100 MB. Triggers in Java Mission Control can use any property exposed through a JMX MBean as the input to the rule. They can launch many other actions than just Flight Recorder dumps.

Define triggers on the Triggers tab of the JMX Console. For more information on how to create triggers, see the Java Mission Control help.

Troubleshooting

You can collect a significant amount of diagnostic information from Java Flight Recorder by starting the JVM with one of the following options:

  • -XX:FlightRecorderOptions=loglevel=debug

  • -XX:FlightRecorderOptions=loglevel=trace.

Java Flight Recorder Command Reference

For a listing of commands you can use with the Java Flight Recorder, see "Command Reference" in Java Platform, Standard Edition Java Flight Recorder Runtime Guide.

Using Java Mission Control

This section describes using Java Mission Control.

Starting the Java Mission Control Client

The JMC client executable file is located in the bin directory of the Java SE Development Kit (JDK) installation path (JAVA_HOME). If the JAVA_HOME/bin directory is in the PATH environment variable, you can start the JMC client by entering jmc at the command-line prompt (shell). Otherwise, you have to specify the full path to the JMC executable:

  • JAVA_HOME/bin/jmc (Linux)

Passing JVM Options To the JMC Launcher

JMC is a Java application, and the JMC client executable is a launcher for this application. JMC startup is controlled by options specified in the jmc.ini file, which is located in the JAVA_HOME/bin directory. Arguments to the -vmargs option in the jmc.ini file are options that are passed to the JVM running the JMC application. You can specify these options to control the way this JVM runs. If you do not want to modify the jmc.ini file, you can specify JVM options on the command line as arguments to the -vmargs option of the jmc command.

Note:

If other options are specified for the jmc command, the -vmargs option must be specified last.

To start the JMC client with your own set of JVM options (overriding those specified in the jmc.ini file), run the following command (separate multiple arguments with spaces):

jmc -vmarg arguments

To start the JMC client with additional JVM options (appending them to those specified in the jmc.ini file), run the following command (separate multiple arguments with spaces):

jmc --launcher.appendVmargs -vmarg arguments

Using a Workspace Directory

If you want to copy your settings for the JMC client to another computer or another user, or use different predefined settings for different applications, add the -data command-line option and define a workspace directory when you start the JMC client:

jmc -data workspace-directory

Using the Java Mission Control GUI

For detailed information on using the Java Mission Control GUI client, see "Java Mission Control Client GUI" in Java Platform, Standard Edition Java Mission Control User's Guide.

Creating Thread and Heap Dumps Using jcmd

You can use the Java utility, jcmd, to diagnostic command requests directly to the JVM. For detailed information on using the jcmd utility, see "The jcmd Utility" in Java Platform, Standard Edition Troubleshooting Guide.

Creating a Heap Dump using jcmd

To create a heap dump using jcmd execute the following command, replacing Process_ID with the process ID of your JVM process and specifying a path and filename for the output file:

jcmd Process_ID GC.heap_sump /path/filename

Note:

JVM heap dumps are generated in the HPROF binary format. You can analyze HPROF heap dumps using the jhat utility. For more information see "jhat" in Java Platform, Standard Edition Tools Reference.

Example 16-1 Creating a Heap Dump

jcmd 5216 GC.heap_dump ~/heapdumps/myheapdump.dprof
  5216:
  Heap dump file created

Creating a Thread Dump using jcmd

To create a thread dump using jcmd execute the following command, replacing Process_ID with the process ID of your JVM process:

jcmd Process_ID Thread.print

Example 16-2 Creating a Thread Dump

jcmd 5216 Thread.print 
5216:
  2014-09-19 13:12:30
  Full thread dump Java HotSpot(TM) 64-Bit Server VM (24.45-b08 mixed mode):
 
  "Thread-21" daemon prio=6 tid=0x0000000016109800 nid=0x1d5c in Object.wait() 
  [0x000000001c22f000] java.lang.Thread.State: TIMED_WAITING (on object monitor)
  at java.lang.Object.wait(Native Method)

Other jcmd Commands

This section provides example jcmd commands.

List All JVM Processes

Run jcmd without any parameters (or with -l) to list all JVM processes preceded by a process ID:

jcmd -l
   6848
   8120 sun.tools.jcmd.JCmd -l
   3108 weblogic.Server

List jcmd Commands for a Particular Process

Run jcmd PID help to list the jcmd commands available for that process. Replace PID with the process ID of your JVM process:

jcmd 3108 help
  The following commands are available:
  VM.native_memory
  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

Get More Information on a jcmd Command

To get more information on a jcmd command run jcmd help command_name where command_name is the name of the jcmd command:

jcmd help GC.heap_dump
  GC.heap_dump
  Generate a HPROF format dump of the Java heap.

  Impact: High: Depends on Java heap size and content. Request a full GC 
  unless the '-all' option is specified.

  Syntax : GC.heap_dump [options] <filename>

  Arguments:
      filename :  Name of the dump file (STRING, no default value)

  Options: (options must be specified using the <key> or <key>=<value> syntax)
  -all : [optional] Dump all objects, including unreachable objects 
  (BOOLEAN, false)

jcmd Command Reference

For a listing of commands you can use with the jcmd utility, see "Command Reference" in Java Platform, Standard Edition Java Flight Recorder Runtime Guide.

The Java Control+Break Handler

On Oracle Solaris or Linux operating systems, the combination of pressing the Control key and the backslash (\) key at the application console (standard input) causes the Java HotSpot VM to print a thread dump to the application's standard output. On Windows, the equivalent key sequence is the Control and Break keys. The general term for these key combinations is the Control+Break handler.

On Oracle Solaris and Linux operating systems, a thread dump is printed if the Java process receives a QUIT signal. Therefore, the kill -QUIT pid command causes the process with the ID pid to print a thread dump to standard output.

For details on Control+Break output see the following sections in the Java Platform, Standard Edition Troubleshooting Guide:

Tuning JVM Garbage Collection for Production Deployments

This Section describes how to tune Java Virtual Machine (JVM) garbage collection performance for Oracle Communications Converged Application Server engine servers.

Goals for Tuning Garbage Collection Performance

Production installations of Converged Application Server generally require extremely small response times (under 50 milliseconds) for clients even under peak server loads. A key factor in maintaining brief response times is the proper selection and tuning of the JVM's Garbage Collection (GC) algorithm for Converged Application Server instances.

Whereas certain tuning strategies are designed to yield the lowest average garbage collection times or to minimize the frequency of full GCs, those strategies can sometimes result in one or more very long periods of garbage collection (often several seconds long) that are offset by shorter GC intervals. With a production Converged Application Server installation, all long GC intervals must be avoided to maintain response time goals.

The sections that follow describe GC tuning strategies for Oracle's JVM that generally result in best response time performance.

Modifying JVM Parameters in Server Start Scripts

If you use custom startup scripts to start Converged Application Server engines and replicas, simply edit those scripts to include the recommended JVM options described in the sections that follow.

The Configuration Wizard also installs default startup scripts when you configure a new domain. by default, these scripts are installed in the Middleware_Home/user_projects/domains/domain_name/bin directory, where Middleware_Home is where you installed the Converged Application Server software and domain_name is the name of the domain's directory. The /bin directory includes:

  • startWebLogic.cmd, startWebLogic.sh: These scripts start the Administration Server for the domain. The also contain a variety of Java configuration settings.

  • startManagedWebLogic.cmd, startManagedWebLogic.sh: These scripts start managed engines and replicas in the domain.

If you use the Oracle-installed scripts to start engines and replicas, you can override JVM memory arguments by first setting the USER_MEM_ARGS environment variable in your command shell.

Note:

Setting the USER_MEM_ARGS environment variable overrides all default JVM memory arguments specified in the Oracle-installed scripts. Always set USER_MEM_ARGS to the full list of JVM memory arguments you intend to use.

Tuning Garbage Collection with Oracle JDK

When using Oracle's JDK, the goal in tuning garbage collection performance is to reduce the time required to perform a full garbage collection cycle. You should not attempt to tune the JVM to minimize the frequency of full garbage collections, because this generally results in an eventual forced garbage collection cycle that may take up to several full seconds to complete.

The simplest and most reliable way to achieve short garbage collection times over the lifetime of a production server is to use a fixed heap size with the collector and the parallel young generation collector, restricting the new generation size to at most one third of the overall heap.

Oracle recommends using the Garbage-First (G1) garbage collector. See "Getting Started with the G1 Garbage Collector" for more information on using the Garbage-First collector.

The following example JVM settings are recommended for most production engine servers:

-server -Xms24G -Xmx24G -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:ParallelGCThreads=20 -XX:ConcGCThreads=5 -XX:InitiatingHeapOccupancyPercent=70

For standalone installations, use the example settings:

-server -Xms32G -Xmx32G -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:ParallelGCThreads=20 -XX:ConcGCThreads=5 -XX:InitiatingHeapOccupancyPercent=70

The above options have the following effect:

  • -Xms, -Xmx: Places boundaries on the heap size to increase the predictability of garbage collection. The heap size is limited in replica servers so that even Full GCs do not trigger SIP retransmissions. -Xms sets the starting size to prevent pauses caused by heap expansion.

  • -XX:+UseG1GC: Use the Garbage First (G1) Collector.

  • -XX:MaxGCPauseMillis: Sets a target for the maximum GC pause time. This is a soft goal, and the JVM will make its best effort to achieve it.

  • -XX:ParallelGCThreads: Sets the number of threads used during parallel phases of the garbage collectors. The default value varies with the platform on which the JVM is running.

  • -XX:ConcGCThreads: Number of threads concurrent garbage collectors will use. The default value varies with the platform on which the JVM is running.

  • -XX:InitiatingHeapOccupancyPercent: Percentage of the (entire) heap occupancy to start a concurrent GC cycle. GCs that trigger a concurrent GC cycle based on the occupancy of the entire heap and not just one of the generations, including G1, use this option. A value of 0 denotes 'do constant GC cycles'. The default value is 45.

Avoiding JVM Delays Caused by Random Number Generation

The library used for random number generation in Oracle's JVM relies on /dev/random by default for UNIX platforms. This can potentially block the Converged Application Server process because on some operating systems /dev/random waits for a certain amount of "noise" to be generated on the host system before returning a result.

To determine if your operating system exhibits this behavior, try displaying a portion of the file from a shell prompt:

head -n 1 /dev/random

If the command returns immediately, you need not continue. If the command does not return immediately, configure the rngd daemon to feed data to the kernel's random number entropy pool:

rngd -r /dev/urandom -o /dev/random -f -t .1

Note:

You may have to experiment with the value of the -t parameter. For more information on the rngd daemon, run the man rngd command from a shell to display this manual page.

Troubleshooting Memory Leaks

If your application's execution time becomes longer and longer, or if the operating system seems to be performing slower and slower, this could be an indication of a memory leak. In other words, virtual memory is being allocated but is not being returned when it is no longer needed. Eventually the application or the system runs out of memory, and the application terminates abnormally.

For more information on diagnosing Java memory leaks, see "Troubleshooting Memory Leaks" in Java Platform, Standard Edition Troubleshooting Guide.

In addition, you can also use the Eclipse Memory Analyzer Tool (MAT) during development to discover memory leaks as well as reduce memory consumption.

For details on the Eclipse MAT, see http://www.eclipse.org/mat/.