Version 9 (modified by paul, 13 years ago) (diff)


Contributed By Igor Malinovski

Heap Layout

The heap is divided into 3 generations, young generation, tenured(old) generation, and permanent generation. Young generation is further divided into an Eden, and Survivors spaces.

Setting Heap Size

A number of parameters affect generation size.. At initialization of the virtual machine, the entire space for the heap is reserved. Thesize of the space reserved can be specified with the -Xmxoption. If thevalue of the -Xmsparameter is smaller than the value of the-Xmxparameter, not all of the space that is reserved is immediately committed to the virtual machine. It is recommended to set -Xms and -Xmx to the same value. Setting -Xms and -Xmx to the same value increases predictability by removing the most important sizing decision from the virtual machine.

For example:

java '''-Xms512m -Xmx512m''' application

Young Generation Heap

The size of the Eden and semi-spaces is controlled by the SurvivorRatio? and can be calculated roughly as: Eden = NewSize -((NewSize / ( SurvivorRatio + 2)) * 2) From space = (NewSize - Eden) / 2 To space = (NewSize - Eden) / 2 NewSize is the size of the young generation and can be specified on the command line using -XX:NewSize option. SurvivorRatio is an integer number and can range from 1 to a very high value.

The young generation can be sized using the following options:-XX:NewSize -XX:MaxNewSize -XX:SurvivorRatio For example, to size a 128 MB young generation with an Eden of 64MB, a Survivor-Space size of 32MB, the NewSize, MaxNewSize, and SurvivorRatiovalues can be specified as follows:

java -Xms512m -Xmx512m -XX:NewSize=128m -XX:MaxNewSize=128m

-XX:SurvivorRatio=2 application

Old Generation Heap

The old generation or the tenured generation is used to hold orage objects promoted from the younger generation. The maximum size of the older generation is controlled by the -Xms parameter.

For the previous example to size a 256 MB old generation heap with a young generation of 256 MB the -mx value can be specified as:

java -Xms512m -Xmx512m -XX:NewSize=256m -XX:MaxNewSize=256m

-XX:SurvivorRatio=2 application

The young generation takes 256 MB and the old generation 256 MB. -Xms is used to specify the initial size of the heap.

Permanent Generation Heap

The permanent generation is used to store class objects and relatedmeta data. The default space for this is 4 MB, and can be sized usingthe -XX:PermSize, and -XX:MaxPermSize option.

Sometimes you will see Full GCs in the log file, and this could be due to the permanent generation being expanded. This could be prevented by sizing the permanent generation with a bigger heap using the-XX:PermSize and -XX:MaxPermSize options.

For example:

java -Xms512m -Xmx512m -XX:NewSize=256m -XX:MaxNewSize=256m

-XX:SurvivorRatio=2 -XX:PermSize=64m -XX:MaxPermSize=64m application

Low Pause Collectors

Parallel Copying Collector (ParNewGC)

The Parallel Copying Collector is similar to the default CopyingCollector, but instead of using one thread to collect young generation garbage, the collector allocates as many threads as the number of CPUs to parallelize the collection. The parallel copying collector works with both the concurrent collector and the default mark-compact collector.

The parallel copying collection is still stop-the-world, but the cost of the collection is now dependent on the live data in the young generation heap, divided by the number of CPUs available.

The figure above illustrates the difference between the singlethreaded and parallel copy collection. The green arrows representapplication threads, and the red arrow(s) represent GC threads. Theapplication threads (green arrows) are stopped when a copy collectionhas to take place. In case of the parallel copy collector, the work is done by n number of threads compared to 1 thread in case of the singlethreaded copy collector.

Concurrent Mark Sweep Collector (CMS)

The concurrent collector uses a background thread that runs concurrently with the application threads to enable both garbage collection and object allocation/modification to happen at the sametime. The collector collects the garbage in phases, two arestop-the-world phases, and four are concurrent and run along with the application threads. The phases in order are, initial-mark phase (stop-the-world), mark-phase (concurrent), pre-cleaning phase (concurrent), remark-phase (stop-the-world), sweep-phase (concurrent) and reset-phase (concurrent). The initial-mark phase takes a snapshot of the old generation heap objects followed by the marking and pre-cleaning of live objects. Once marking is complete, a remark-phase takes a second snapshot of the heap objects to capture changes in live objects. This is followed by a sweep phase to collect dead objects -coalescing of dead objects space may also happen here. The reset phase clears the collector data structures for the next collection cycle. The collector does most of its work concurrently, suspending application execution only briefly.

The figure above illustrates the main phases of the concurrent collection. The green arrows represent application threads, and thered, GC thread(s). The small red arrow represents, the brief stop-the-world marking phases, when a snapshot of the heap is made. The GC thread (big red arrow) runs concurrently with application threads (green arrows) to mark and sweep the heap.

JVM GC Options

The young generation, parallel copying collector can be enabled by using the -XX:+UseParNewGC option, while the older generation, concurrent collector can be enabled by using the -XX:+UseConcMarkSweepGC option.

By default, the parallel copy collector will start as many threads as CPUson the machine, but if the degree of parallelism needs to controlled,then it can be specified by the following option: -XX:ParallelGCThreads=<desired number of threads> The number of times an object is aged in the young generation is controlled by the option MaxTenuringThreshold. Setting this option to 0means objects are not copied, but are promoted directly to the older generation. SurvivorRatio? should be increased to 20000 or a high value so that Eden occupies most of the Young Generation Heap space: -XX:MaxTenuringThreshold=0 -XX:SurvivorRatio=20000

The concurrent collector background thread starts running when thepercentage of allocated space in the old generation goes above the -XX:CMSInitiatingOccupancyFraction, default value is 60%. This value can be changed and the concurrentcollector can be started earlier by specifying the following option: -XX:CMSInitiatingOccupancyFraction=<percent> . The concurrentcollector also keeps statistics on the promotion rate into the oldgeneration for the application and makes a prediction on when to start a concurrent collection based on that promotion rate and the available free space in the old generation. Whereas the use !ofCMSInitiatingOccupancyFraction must be conservative to avoid full collections over the life of the application, the start of a concurrent collection based on the anticipated promotion adapts to the changing requirements of the application. To eliminate the use of the anticipated promotions to start a concurrent collection setUseCMSInitiatingOccupancyOnly to true by -XX:+UseCMSInitiatingOccupancyOnly.

Other useful option is -XX:+CMSParallelRemarkEnabled. It allows to use multiple threads during CMS remark phase to decrease CMS remark pauses. Some Java libraries (like RMI) may want to call GC from Javacode. In such cases JVM runs Full GC, which stops the application for a long time. Such behaviour is inadmissible for telco applications. Thus the execution of GC from application should be disabled with -XX:+DisableExplicitGC

In general, the optimal GC options for telco applicition looks following:

-XX:+UseParNewGC -XX:+UseConcMarkSweepGC-XX:MaxTenuringThreshold=0 

Related documentation

Tuning Garbage Collection with the 5.0 Java Virtual Machine

GC output example

Frequently Asked Questions about Garbage Collection

Java Performance Documentation