Contributed By Igor Malinovski
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. The size of the space reserved can be specified with the -Xmx option. If the value of the -Xms parameter is smaller than the value of the -Xmx parameter, 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.
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
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 -Xmx value can be specified as:
java -Xms512m -Xmx512m -XX:NewSize=256m -XX:MaxNewSize=256m
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.
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 -XX:SurvivorRatio=20000 -XX:CMSInitiatingOccupancyFraction=60 -XX:+UseCMSInitiatingOccupancyOnly -XX:+CMSParallelRemarkEnabled -XX:+DisableExplicitGC