1. Welcome Developer Playground by Giri
JVM Performance

About G1 GC

Updated: March 31, 2025

Introduction to G1 GC

G1 GC has been available since Java 7 and was designated as the default garbage collector in Java 9. It is suitable for multi-processor machines with large memory.

It attempts to achieve the configured target stop-the-world time with high probability. The goal is to make the pause time as predictable and short as possible.

G1 aims for high throughput while minimizing the need for user configuration. The goal is to prevent developers from spending too much time optimizing performance.

Target Applications

  • Environments with heap sizes from a few GB to a maximum of 10GB
  • Environments where object allocation and promotion rates can vary significantly in real-time
  • Environments where a significant level of fragmentation may occur in the heap
  • Cases requiring predictable stop-the-world times not exceeding hundreds of milliseconds

G1 GC replaces the CMS (Concurrent Mark-Sweep) garbage collector.

It divides the heap into multiple regions and aims to achieve high performance by processing these regions concurrently during garbage collection.

Activating G1 GC

As the default garbage collector, no special configuration is required. It can be explicitly enabled through -XX:+UseG1GC.

Basic Concepts

Like other garbage collectors, G1 uses the concept of generational memory lifecycle with young and old generations. It performs garbage collection incrementally using multiple threads. To improve throughput, some garbage collection tasks can proceed while the application is running, while some critical tasks cause stop-the-world pauses.

Heap Layout

G1 divides the heap into a set of equally-sized heap regions, each consisting of contiguous ranges of virtual memory. Regions are the unit of memory allocation and reclamation. At any time, a region can be empty or allocated to the young generation or old generation. When a memory request comes in, the memory manager allocates free regions. The memory manager assigns free regions to generations and returns free regions to the application so that the application can allocate to these regions.

Eden
S
H
S
Young Generation (Eden and Survivor regions)
Old Generation

The young generation consists of eden regions (red) and survivor regions (red with "S" written). Unlike other garbage collectors that provide the same functionality with adjacent spaces, G1 GC has the distinction of placing memory in a non-contiguous pattern.

The old generation is represented by the blue regions in the figure. Large objects like "H" can occupy multiple regions.

Applications always allocate to the eden regions of the young generation. Exceptionally, very large objects may be allocated directly to the old generation.

G1 GC pauses can reclaim space from the entire young generation and can also return space from the old generation. During pauses, G1 uses aging to copy objects to other regions of the heap. Objects that were in the young generation are copied to survivor or old regions, and objects that were in old regions are copied to other old regions.

Garbage Collection Cycle

At a high level, G1 alternates between two phases as shown in the image below:

  1. Young-Only Phase
  2. Space Reclamation Phase

1. Young-only phase

This begins with the process of promoting objects to the old generation. The transition between the young-only phase and the space-reclamation phase occurs when the old generation's memory occupancy reaches a specific threshold (the Initiating Heap Occupancy threshold). At this point, G1 schedules an Initial Mark young-only collection instead of a regular young-only collection.

Initial Mark

Starts the marking process along with a regular young-only collection. Concurrent Marking determines which live objects in the old generation to keep for the next space-reclamation phase. Regular young collections can continue while marking is in progress. Marking ends with two stop-the-world pauses called Remark and Cleanup.

Remark

The Remark pause finalizes marking by performing global reference processing and class unloading. Between Remark and Cleanup, G1 concurrently calculates a summary of the liveness information, which is finally used to modify internal data structures during the Cleanup pause.

Cleanup

This pause reclaims completely empty regions and determines whether the space-reclamation phase will follow. If the space-reclamation phase follows, the young-only phase ends with a single young-only collection.

2. Space-reclamation phase

This consists of Mixed collections that cause objects to move from both young generation regions and old generation regions. This phase ends when G1 determines that it cannot free up sufficient space in the old generation. After space-reclamation ends, the collection cycle starts again with another young-only phase. As a backup, if the application runs out of memory while collecting liveness information, G1, like other garbage collectors, performs an in-place stop-the-world full heap compaction (Full GC).

Garbage-First Internals

Determining Initial Heap Occupancy (IHOP)

This is the threshold at which Initial Mark collection is triggered and is determined as a percentage of the old generation size. G1 uses this concept to predict latency. G1 determines the optimal IHOP by observing how long marking takes during a marking cycle and how much memory is allocated to the old generation. This feature is called Adaptive IHOP. When adaptive IHOP is active, the -XX:InitiatingHeapOccupancyPercent option sets the initial value as a percentage of the current old generation size (default 45%) when there haven't been enough observations to make a good threshold prediction. The -XX:-G1UseAdaptiveIHOP option is used to disable this feature. When disabled, the -XX:InitiatingHeapOccupancyPercent value always determines the threshold. Internally, Adaptive IHOP tries to set the IHOP so that the first mixed GC of the space-reclamation phase starts when the old generation occupancy is at the current maximum old generation size minus the -XX:G1HeapReservePercent value as an additional buffer.

Marking

G1 marking uses an algorithm called Snapshot-At-The-Beginning (SATB). It creates a virtual snapshot of the heap at the time of the Initial Mark pause, when all objects that were alive are excluded from marking and survive. This means that objects that become garbage during marking are still considered live for the space-reclamation phase. This may result in some additional memory misuse compared to other garbage collectors, but SATB offers potentially lower latency during the Remark pause. Objects that are conservatively considered alive during marking will be reclaimed in subsequent markings.

Out of Memory Situations

Evacuation may fail when an application continues to operate while using too much memory, making the heap somewhat tight. G1 attempts to complete collection by leaving already moved objects moved and unmoved objects in place, adjusting only the references between objects. Evacuation failure can cause additional overhead but generally proceeds as quickly as a normal young collection. After a collection that ends with evacuation failure, G1 resumes the application as normal without additional measures. G1 assumes that evacuation failure occurred as collection was nearing completion. That is, most objects were already successfully moved, and there is enough space for the application to continue running until marking completes and space-reclamation begins. If this assumption does not hold, G1 will eventually schedule a very slow Full GC that performs in-place compaction on the entire heap.

Humongous Objects

Objects larger than half the size of a region are Humongous objects. The current region size is determined ergonomically by G1 unless set with the -XX:G1HeapRegionSize option.

These large objects are sometimes managed in a special way:

  • They are allocated in contiguous regions in the old generation.
  • Generally, humongous objects can only be reclaimed during the Cleanup pause at the end of marking or during a Full GC.
  • For objects like primitive type arrays that are not referenced by many objects, G1 attempts to reclaim humongous objects at every type of garbage collection pause. This feature is enabled by default but can be disabled via the -XX:G1EagerReclaimHumongousObjects option.
  • Allocation of a humongous object may lead to premature gc pauses because G1 checks the Initiating Heap Occupancy threshold whenever a humongous object is allocated and may immediately force an initial mark young collection if the threshold is exceeded.
  • Humongous objects are never moved, even during a Full GC. This can lead to early slow Full GCs due to space fragmentation or unexpected out-of-memory conditions, even if there are many free regions.

Young-Only Phase Generation Sizing

During the young-only phase, the collection set, that is, the set of regions to be collected, consists only of young generation regions. G1 always adjusts the size of the young generation at the end of a young-only collection. G1 observes actual pause times over the long term. G1 adjusts the young generation size to achieve the pause time goal set by -XX:MaxGCPauseTimeMillis and -XX:PauseTimeIntervalMillis. G1 also considers how long pause times have taken for similar-sized young generations, how many objects have moved to other regions during collection, and how related they are to each other. G1 adjusts the size of the young generation to achieve the target pause time within the limits set by -XX:G1NewSizePercent and -XX:G1MaxNewSizePercent.

Space-Reclamation Phase Generation Sizing

Space-reclamation proceeds with the goal of reclaiming as much space as possible from the old generation during a gc pause. The young generation size is set to the minimum allowed, typically determined by the -XX:G1NewSizePercent option. G1 continues to add old generation regions without exceeding the target pause time. G1 adds old generation regions in order of reclamation efficiency, starting with the most efficient regions and determining the final set of regions to reclaim based on the remaining pause time.

The -XX:G1MixedGCCountTarget option sets the length of the space-reclamation phase. This setting determines the minimum number of old generation regions to reclaim per collection. Candidate regions for reclamation are all old generation regions with occupancy lower than -XX:G1MixedGCLiveThresholdPercent at the start of the space-reclamation phase. The space-reclamation phase ends when the amount of reclaimable space remaining in the candidate regions is less than the percentage set by -XX:G1HeapWastePercent.

Differences from Other Garbage Collectors

Parallel GC compacts and reclaims the old generation in its entirety, while G1 GC proceeds incrementally with short collections over multiple passes. This allows G1 to achieve shorter pause times by sacrificing throughput.

Similar to CMS GC, G1 GC performs old generation space-reclamation concurrently. However, CMS GC cannot compact the old generation, which eventually leads to a long Full GC.

G1 may incur more overhead in throughput than other garbage collectors because it performs collections concurrently.

Due to this mode of operation, G1 increases efficiency through special mechanisms:

  • G1 can reclaim large completely empty regions in the old generation from any collection. This allows for allocating large amounts of memory. This feature is enabled by default and can be disabled via the -XX:-G1EagerReclaimHumongousObjects option.
  • G1 can eliminate string duplicates concurrently. This feature is disabled by default and can be enabled via -XX:+G1EnableStringDeduplication.

JDK 24 Updates for G1 GC

JDK 24, released in March 2025, includes several improvements to G1 GC. While not tied to specific major JEPs (JDK Enhancement Proposals), these changes enhance G1's performance and reliability:

Key G1 GC Improvements in JDK 24

  • Enhanced Adaptive IHOP Algorithm

    Refinements to the algorithm for determining when to start concurrent marking, leading to better prediction and fewer unexpected pauses.

  • Improved Humongous Object Handling

    Better management of large objects to reduce fragmentation and decrease the likelihood of full GC events.

  • Optimized Remembered Set Scanning

    Improved efficiency of remembered set scanning during garbage collection, reducing pause times in applications with large heaps.

  • Region Allocation Performance

    Optimized the process of allocating new regions during garbage collection, reducing latency spikes in high-throughput applications.

  • Evacuation Failure Handling

    Fixed issues where G1 evacuation failures could lead to suboptimal memory utilization, potentially causing more frequent garbage collections.

Additionally, JDK 24 includes general GC improvements that benefit G1:

  • Better Container Adaptation: Improved detection and response to containerized environments, particularly valuable for cloud deployments.
  • Reduced CPU Overhead: Optimizations to lower CPU usage during concurrent GC operations, allowing more resources for the application.

These improvements make G1 GC in JDK 24 more efficient, predictable, and less intrusive to application performance, particularly for large-scale enterprise applications with significant memory requirements.

References

Copyright © 2025 Giri Labs Inc.·Trademark Policy