We all know the importance of Java GC, but the huge number of writings on the topic can be difficult to grasp, so I've written this post to help sort out some of the confusion (especially in terminology).
Note that you may need to have some basic understanding of how GC works. If not, these two links provide a good introduction:
The Generational Heap
Generation
|
What’s
on it
|
Young
gen (aka. New gen)
|
The
pool from which memory is initially allocated for most objects.
|
Old
gen (aka. Tenured space)
|
The pool containing
objects that have existed for some time in the survivor space.
|
Perm
gen
|
The
pool containing all the reflective data of the virtual machine itself, such
as class and method objects.
|
Code
cache
|
Memory that is used
for compilation and storage of native code.
|
HotSpot Memory Layout |
heap = young gen (aka. new gen) + old gen (aka. tenured space)
young gen = eden space + survivor space 1 + survivor space 2
One important point to bear in mind:
Almost all objects on heap will die (apart from application scoped objects), either when they're young or old, so the overall used heap size should be related to the rate of object creation and their lifetime only, not how long the application has run (unless there is a memory leak).
The Collectors
This link (also this one) provides a good overview of the types of collectors as well as their combination in HotSpot.
This table summarises all collectors (apart from G1 collector):
Compaction Collector
|
Non
Compaction Collector
|
|
Serial
(Single thread)
|
Young gen:
Serial
collector (aka. Copy collector) (-XX:+UseSerialGC)
Old gen:
Mark Sweep
Compact (aka. Serial old collector, MSC) (-XX:+UseSerialGC), note this is the
default old GC
|
None
|
Parallel
(Multi thread)
|
Young gen:
Parallel collector
(aka. Parallel scavenge, PS) (-XX:+UseParallelGC), only works with serial/parallel
old collector
Parallel new collector
(-XX:+UseParNewGC), mainly works with CMS, but also works with MSC (because
of full GC)
Old gen:
Parallel Scavenge Mark
Sweep Compact (aka. Parallel MSC) (-XX:+UseParallelOldGC), note this will
force -XX:+UseParallelGC
|
None
|
Concurrent
|
None
|
Old gen:
Concurrent
Mark Sweep (-XX:+UseConcMarkSweepGC), note this only works with -XX:+UseParNewGC
or -XX:-UseParNewGC (i.e., use serial collector)
|
Let me just highlight some important points:
- A minor collection happens on young gen only, while a major collection (aka. full GC) on the entire heap.
- A major collection is triggered when old gen is full. It collects the old gen first, then the young gen, promoting qualified objects to old gen.
- Stop-the-world events are not bad. All collector pauses are stop-the-world (whether it's a young gen collector or an old gen one), in order to calculate the GC roots and possibly compacting the heap or copying objects (to survivor spaces). What is bad is a major collection that stops the world for too long, or lots of frequent minor collections that add up to long pause time.
- A full GC is slow because it involves compacting the heap (i.e., relocating live objects in old gen so they are close together).
- CMS (concurrent-mark-sweep) collector tries to avoid full GC (hence better response time) at the cost of throughput (because the collector runs concurrently with the application threads). When a full GC is inevitable (either old gen is full, overly fragmented, or it cannot catch up with object creation rate), it falls back to the parallel collector to compact the heap (just once).
- A rule of thumb: parallel GC for throughput, concurrent GC for response time.
Ways to Tune
There are two main ways to tune a JVM, as documented in Java SE 6 HotSpot GC tuning
1. Explicitly setting the heap and off-heap parameters
2. Using ergonomics (only works for parallel collectors)
Also see here for a list of all JVM options in Java 6.
How to Monitor GC
jstat -gcutil <prid> <period in ms>
References
- Generational heap: http://stackoverflow.com/a/1262474/842860
- Java Garbage Collection Basics: http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html
- Java SE 6 HotSpot GC tuning: http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html
- http://www.infoq.com/articles/Java_Garbage_Collection_Distilled
- http://javabook.compuware.com/content/memory/how-garbage-collection-works.aspx
- http://www.fasterj.com/articles/oraclecollectors1.shtml
- Minor GC, with a list of all possible collector options: http://blog.griddynamics.com/2011/06/understanding-gc-pauses-in-jvm-hotspots.html
- CMS: http://blog.griddynamics.com/2011/06/understanding-gc-pauses-in-jvm-hotspots_02.html
- TLAB: http://stackoverflow.com/a/25515423/842860
- List of JVM options for 1.6: http://stas-blogspot.blogspot.co.uk/2011/07/most-complete-list-of-xx-options-for.html