Skip navigation.
Downloads | Product Documentation | Support

Using JRockit SDK

# Using the BEA JRockit Memory Management System

Memory management relies on effective "garbage collection," the process of clearing dead objects from the heap, thus releasing that space for new objects. Effective memory management ensures efficient processing. BEA JRockit's unified garbage collector allows you to select a dynamic garbage collector based solely upon one of two priorities: memory throughput or duration of pause time caused by collection. The unified garbage collector is dynamic in that, as it runs, it uses predefined heuristics to determine which collection algorithm to use and changing that algorithm as the individual case might warrant. You do not need to specify the actual algorithm to run this garbage collector.

In some instances, dynamic garbage collection might not be the most effective way to free-up memory. In those cases, BEA JRockit also provides a number of "static" collectors that can be started either by specifying the actual collector (`-Xgc:<``collectorName``>`) or by default, as determined by the JVM mode you select at startup.

This section describes how to use all of these garbage collection methods. It contains information on the following subjects:

- The Mark-and-Sweep Collection Model
- Garbage Collector Permutations
- Running the Dynamic Garbage Collector
- Using Static Garbage Collection Methods
- Overriding Garbage Collectors
- Viewing Garbage Collection Activity
- Thread-local Allocation

# The Mark-and-Sweep Collection Model

The unified garbage collector is a mark-and-sweep collector that runs either as generational or single-spaced; that is, with or without a "nursery" (see Generational, below). Both mark-and-sweep options can implement either a concurrent or parallel algorithm. Please refer to Garbage Collector Permutations for more information on garbage collection options and algorithms.

A mark-and-sweep collector is a three-pass model that frees all unreferenced objects. It works as described in these steps:

1. The first pass clears all objects in the system that have their mark bit set. The mark bit identifies whether the block is in use if the block contains garbage.
2. The second pass, or "mark" phase, traverses all pointers, starting at the accessible roots of a program (conventionally, globals, the stack, and registers) and marks each object traversed.
3. The third pass, or "sweep" phase, re-walks the heap linearly and removes all objects that are not marked.

# Garbage Collector Permutations

The unified garbage collector is comprised of various permutations—or "states"—of two garbage collector options:

- Generational
- Single-spaced

and two garbage collection algorithms:

- Concurrent
- Parallel

## Generational

In generational garbage collection, the heap is divided into two sections: an old generation and a young generation—also called the "nursery." Objects are allocated in the nursery and when it is full, the JVM "stops-the-world" (that is, stops all threads) and moves the live objects in the young generation into the old generation. At the same time, an old collector thread runs in the background, marking live objects in the old generation and removing the dead objects, returning free space to JVM.

## Single-spaced

The single-spaced option of garbage collection means that all objects live out their lives in a single space on the heap, regardless of their age. In other words, a single-spaced garbage collector does not have a nursery.

## Concurrent

The concurrent garbage collection algorithm does its marking and/or sweeping "concurrently" with all other processing; that is, it does not stop Java threads to do the complete garbage collection.

## Parallel

The parallel garbage collection algorithm stops Java threads when the heap is full and uses every CPU to perform a complete mark and/or sweep of the entire heap. A parallel collector can have longer pause times than concurrent collectors, but it maximizes throughput. Even on single CPU machines, this maximized performance makes parallel the recommended garbage collector, provided that your application can tolerate the longer pause times.

# Running the Dynamic Garbage Collector

The unified garbage collector combines the options and algorithms described above within the mark-and-sweep model to perform collection. Depending upon the heuristics used, the collector will employ a generational or single-spaced collector with either a concurrent or parallel mark phase and a concurrent or parallel sweep phase.

The main benefit of a dynamic—or "optimizing"—garbage collector is that the only determination you need to make to run the collector best-suited to your needs is whether your application responds best to optimal memory throughput during collection or minimized pause times at that time. You do not need to understand the garbage collection algorithms themselves, or the various permutations thereof, just the behavior of your application.

To start the unified garbage collector, use the `-Xgcprio` command line option with either the `throughput` or `pausetime` parameter, depending upon which priority you want to use:

>     -Xgcprio:<throughput|pausetime>

Table 3-1 describes the priorities under which you can start a dynamic garbage collector and the parameters used to select that priority.

Table 3-1 -Xgcprio Option Priorities

Priority | Description | Parameter
--- | --- | ---
Memory Throughput | Memory throughput is usually the most important priority for garbage collection and the one you will probably select most often. It measures the time between when an object is no longer referenced and the time that it's reclaimed and returned as free memory. The higher the memory throughput the shorter is the time between the two events. Moreover, the higher the memory throughput the smaller the heap you will need. | `throughput`
Pause Time | Pause time is the length of time that the garbage collector stops all Java threads during a garbage collection. The longer the pause, the more unresponsive your system will be. The longest pause time and the average pause time during an application run are extremely useful values for tuning the JVM. You will most commonly select pause time as your top priority when you know that your system is sensitive to lengthy pauses. | `pausetime`

Upon selecting the priority and starting the JVM, the dynamic garbage collector will then try to choose the garbage collection state that optimizes performance based upon the priority. It will seek modes that optimize throughput when `-Xgcprio:throughput` is set or that minimize the pause times (as much as possible) when `-Xgcprio:pausetime` is set.

# Using Static Garbage Collection Methods

In some circumstances, you might not want to use a dynamic garbage collector. In those cases, you can use a static collector started by default or by selecting one of the backwardly-compatible garbage collectors provided in earlier versions of BEA JRockit. Unlike the dynamic garbage collector started with `-Xgcprio`, static collectors do not change from the algorithm originally selected to collect garbage. They will not attempt to optimize performance by changing algorithms.

This section contains information on the following subjects:

- Using Backward-compatible Garbage Collectors
- Setting the Default Garbage Collector

## Using Backward-compatible Garbage Collectors

Three static garbage collectors originally available in earlier versions of BEA JRockit SDK are still available for your use in this version. In some circumstances, the performance of these collectors might meet your needs better than the unified collector or the default collectors available with the `-server` or `-client` flags. Additionally, if you want to use scripts written for the earlier versions of BEA JRockit that implement these collectors, those scripts will continue to work without requiring any modification—unless they use the generational copy garbage collector, which is no longer available (of course, your scripts can be modified to implement the unified garbage collector).

The available garbage collectors (and the command to start them) are:

- Single-spaced Concurrent (`-Xgc:singlecon`; this is the default garbage collector when BEA JRockit is run in the `-client` mode)
- Generational Concurrent (`-Xgc:gencon`)
- Parallel (`-Xgc:parallel`; this is the default garbage collector in the `-server` mode)

### Pros and Cons

Table 3-2 lists the pros and cons of each garbage collector.

Table 3-2 Garbage Collector Pros and Cons

Garbage Collector | Pros | Cons
--- | --- | ---
Single Spaced Concurrent | Virtually removes all pauses. Can handle gigabyte-sized heaps. Default garbage collector when running with the -client option. | Trades memory for fewer pauses. If ordinary Java threads create more garbage than this collector can collect, pauses occur while these threads are waiting for the collector to complete its cycle. Only effective so long as the program doesn't run out of memory during collection.
Generational Concurrent | Virtually removes all pauses. Has a higher memory throughput than single spaced concurrent garbage collector. Reduces the risk of running out of allocatable memory during collection because the old space is not filled at the same speed. | Trades memory for fewer pauses. If ordinary Java threads create more garbage than this collector can collect, pauses occur while these threads are waiting for the collector to complete its cycle.
Parallel | Uses all processors during collection, thus maximizing memory throughput. Default garbage collector when running with the -server option (default behavior). | "Stop the world" might cause a longer than desirable pause in processing.

### Garbage Collector Selection Matrix

Table 3-3 is a matrix that you can use to determine which garbage collector is right for your BEA JRockit JVM implementation. Use the If... column to locate a condition that matches your implementation and select the garbage collector indicated in the Select this Garbage Collector... column. The third column lists the supported garbage collector that might suit your needs as well as—if not better than—an unsupported collector.

Table 3-3 Garbage Collector Selection Matrix

If You... | Select this Garbage Collector... | Or use...
--- | --- | ---
Cannot tolerate pauses of any length. Employ gigabyte-sized heaps. Willing to trade memory thoughput for eliminating pauses. Have a single CPU machine with a lot of memory. | Single Spaced Concurrent | `-Xgcprio:pausetime`
Cannot tolerate pauses of any length. Employ gigabyte-sized heaps. Willing to trade some memory thoughput for eliminating pauses. Want better memory throughput than possible with Single Spaced Concurrent. Are not sure that the other two methods would be adequate given how you've implemented BEA JRockit JVM. | Generational Concurrent | `-Xgcprio:`pausetime
Using a machine with four CPUs or better or a single CPU machine with a lot of memory. Can tolerate the occasional long pause Need to maximize memory throughput | Parallel | `-Xgcprio:throughput`

## Setting the Default Garbage Collector

If you don't set `-Xgcprio` or `-Xgc` at startup, BEA JRockit defaults to a preselected, static garbage collector based upon the JVM mode you select: server-side (`-server`; the default) or client-side (`-client`). These are not garbage collectors themselves, but JVM configuration options that start a static collector and set default initial and maximum heap sizes. Table 3-4 describes how these startup options set a garbage collector.

Table 3-4 Garbage Collectors Started by JVM Modes

JVM Mode | Description
--- | ---
`-server` | By definition, BEA JRockit is a server-side JVM, thus the `-server` option replicates BEA JRockit's default behavior. When you select `-server`, BEA JRockit will run Parallel garbage collector (equivalent to setting `-Xgc:parallel`). For information on how `-server` sets heap and nursery size, please refer to Setting the Maximum Heap Size and Setting the Minimum Heap Size in Tuning BEA JRockit.
`-client` | When you start BEA JRockit in the `-client` mode, you are asking it to behave as a client-side JVM. This mode is appropriate when you have a smaller heap and are anticipating shorter runtimes for your application. When you select `-client` at JVM startup, BEA JRockit will run a Single-spaced Concurrent garbage collector (equivalent to setting `-Xgc:singlecon`). For information on how `-client` sets heap and nursery size, please refer to Setting the Maximum Heap Size and Setting the Minimum Heap Size in Tuning BEA JRockit.

For more information on using the `-server` and `-client` options, please refer to Starting and Configuring BEA JRockit JVM.

# Overriding Garbage Collectors

Setting `-Xgcprio` will override any settings associated with`-server` and `-client`. Setting `-Xgc` will override `-Xgcprio` and `-server` and `-client`.

# Viewing Garbage Collection Activity

To observe garbage collection activity, use one or both of the options described here. Using these options will help you evaluate the effectiveness of the selected garbage collector and make necessary tuning decisions.

- If you want to see a comprehensive report of garbage collection activity, enter the `-Xgcreport` option at startup. This option causes BEA JRockit JVM to print a comprehensive garbage collection report at program completion.
- If you want to see garbage collection activity when it occurs, enter the `-Xgcpause` option.This option causes the VM to print a line each time Java threads are stopped for garbage collection.

Combining these two options is a very good way of examining the memory behavior of your application; for example:

>     -java -Xgcreport -Xgcpause myClass

# Thread-local Allocation

Thread-local allocation removes object allocation contention and reduces the need to synchronize between threads allocating memory on the heap. It also increases cache performance on a multi-CPU system, because it reduces the risk of two threads running on different CPUs needing to access the same memory pages at the same time.

Thread-local allocation is not the same thing as thread-local objects, but many people tend to confuse the two terms. Thread-local allocation does not determine whether the objects can be accessed from a single thread only (that is, thread-local objects); thread-local allocation means that the thread has an area of its own where no other thread will create new objects. The objects that the thread creates in that area may still be reached from other threads.