- <Inside the Java Virtual Machine>
- <Java Performance - The Definitive Guide>
Nearly every JVM uses generational garbage collectors. They work by splitting the heap into different generations:
- Old generation (tenured generation)
- Young generation, which is further divided into sections: Eden and Survivor spaces.
GC for the young generation is called minor GC. All GC algorithms have stop-the-world pauses during collection of the young generation.
- Objects that are no longer in use are discarded, and objects that are still in use are moved elsewhere.
- all objects in eden are either moved to the unused survivor space(To survivor space) or discarded:
- all objects in From survivor space are either discarded or moved to the unused survivor space(To survivor space) or moved to the old generation (when still liveable after a few minor GC).
- Since all objects are moved, the young generation is automatically compacted when it is collected.
- After every minor GC, the From survivor space and To survivor space are swapped.
GC for the old generation collection is called full GC. Concurrent collectors scan for unused objects can occur without stopping application threads, such as CMS and G1.
Early GC uses reference counting strategy. But now nearly all the GCs use Tracing garbage strategies, which trace out the graph of object references starting with the root nodes.
The basic tracing algorithm is called “mark and sweep” :
- In the mark phase, the garbage collector traverses the tree of references and marks each object it encounters.
- In the sweep phase, unmarked objects are freed, and the resulting memory is made available to the executing program.
In the JVM, the sweep phase must include finalization of objects. Two strategies for defragmentation: compacting and copying
**compacting algorithm **slides live objects over free memory space toward one end of the heap
copying algorithm moves all live objects to a new area, placed side by side with current area.
serial GC throughput / parallel GC CMS GC G1 designed for client machine: 32bit JVM on Windows or single processor machine (default) server machine: multi-CPU Unix machine or 64-bit JVM (default) process large heaps (greater than about 4 GB) with minimal pauses divides the heap into a number of regions minor GC performs with single thread stop all application threads performs with multiple threads stop all application threads performs with multiple threads stops all application threads performs with multiple threads stops all application threads full GC performs with single threads stop all application threads performs with multiple threads stop all application threads uses one or more background threads to periodically scan through the old generation don’t stop application threads processed by background threads don’t need to stop the application threads flag -XX:+UseSerialGC -XX:+UseParallelGC -XX:+UseParallelOldGC -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+UseG1GC when too fragmented -> serial colletor G1 can clean up objects from the old generation by copying from one region into another,it (at least partially) compacts the heap during normal processing less likely to be fragmented
Parallelism / Serialism: there is a single thread or multiple threads for the GC?
Concurrency: the GC threads are running exclusively or along with the application threads? If exclusively, that’s when the “stop-the-world” happens.
You can see, all GC algorithms use “stop-the-world” when doing minor GC.
- a minor GC will be triggered when the new generation is full
- a full GC will be triggered when the old generation is full, or a concurrent GC (if applicable) will be triggered when the heap starts to fill up.
Default GC for server class machine. The throughput matters!
Multi-threaded young generation (minor) GC with single threaded old generation (full) GC -XX:+UseParallelGC default GC in Java 6 through Java 7 update 3.
Multiple-threaded young generation (minor) GC with multi-threaded old generation (full) GC -XX:+UseParallelOldGC default GC in Java 7 update 4 or over.
Both young generation and old generation GC(both minor and full GC) are “stop-the-world” events.
CMS is the Concurrent Mark-and-Sweep collector.
The minor GC has no difference with Parallel collector, but the full GC cycle is _mostly_ concurrent and includes several phases: initial mark phase, concurrent mark & pre-cleaning phase, remark phase, concurrent sweep phase.
There are still “stop-the-world” events in the initial mark and remark phases.
Trigger when young generation exhausted
full GC (Concurrent Cycle)
- mostly concurrent old generation GC, some phases run concurrently with the application, some are “stop-the-world”, some phases are single threaded.
- does not compact old generation, but the “stop-the-world”, single threaded compaction will occur if: 1) concurrent cycle not keeping up 2) too fragment.
Triggered at old generation space occupancy threshold – default is around 70%. This can be adjusted by
Phases initial-mark phase “stop-the-world” single threaded concurrent marking phase run concurrently with the application multi-threaded pre-cleaning phase run concurrently with the application multi-threaded remark phase “stop-the-world” multi-threaded concurrent sweeping phase run concurrently with the application multi-threaded
PerGen collection enable
Permanent generation space can also be collected concurrently by set:
G1 is Garbage First.
G1 uses a drastically different Java heap layout to the other garbage collectors in the HotSpot VM. It splits the Java heap into equal-sized chunks called regions. Even though G1 is generational, it does not have physically separate spaces for the young and old generations. Instead, each generation is a set of (maybe noncontiguous) regions.
PerGen(JDK 7) / metaspace (JDK 8)