HardπŸ‘€ 8-15 years 4 min read Updated Aug 24, 2026

How G1 GC Works β€” Regions, Mixed Collections & Humongous Objects

Reviewed by Gurusankar M. Β· Updated Aug 24, 2026

Asked inAmazonGoogleMicrosoft
#g1#regions#mixed gc#humongous#pause target
Report issue

⚑ Short Answer

G1 divides the heap into equal-size regions dynamically tagged Eden/Survivor/Old. It collects the regions with the most garbage first ('garbage first') to meet a pause target. Mixed GCs collect young + some old regions; objects larger than half a region are 'humongous' and handled specially.

β˜•Coffee Chat Question

Concept Made Simple

β€œHow does G1 GC work internally β€” regions, mixed collections and humongous objects?”

🧠Mind Map Answer

Remember It Faster

Regions→heap split into equal regions
Garbage-first→collect highest-garbage regions
Mixed GC→young + selected old regions
Humongous→> 50% region → spans regions

MaxGCPauseMillis is a soft target, not a hard guarantee. G1 tracks how much garbage each region yields per unit of collection time, and before every collection it picks however many regions it estimates it can collect within the pause target β€” it literally sizes the work to fit the time budget, region by region, rather than committing to a fixed collection set up front. Set the target too low and G1 shrinks the collection set to compensate, which means it reclaims less garbage per pause and has to run pauses more often β€” 'lower pause target' can paradoxically mean more total time spent pausing, not less.

Humongous objects are costly for two compounding reasons. First, any object bigger than half a region size is allocated directly into a run of contiguous free regions (skipping the normal young-gen allocation path entirely), which can force an otherwise-unnecessary GC just to free up that much contiguous space. Second, those humongous regions live in old gen from birth and are only reclaimed during a full region-emptying collection β€” they can't be partially collected the way normal old regions can during a mixed GC, so a large array that becomes garbage still sits there, uncollected, until G1 does a collection that happens to fully empty its region.

Tuning G1HeapRegionSize: because the humongous threshold is defined as half a region, the practical fix for frequent humongous allocations is usually raising the region size itself (-XX:G1HeapRegionSize=32m, for example) so the objects triggering it no longer cross that 50% line β€” not shrinking the objects. Region size must be a power of two between 1MB and 32MB; G1 auto-selects a default based on heap size, but a workload with consistently large allocations (image buffers, large batch payloads) benefits from setting it explicitly rather than relying on the auto-picked default.

Remembered sets are what let G1 collect a handful of young regions without scanning the entire heap for roots. A young-only collection needs to know every old-gen object that references a young object (otherwise a live young object could be missed as garbage), but scanning all of old gen on every minor collection would defeat the purpose of region-based, incremental collection entirely. Instead, each region keeps a remembered set (RSet) β€” a running list of which other regions point into it β€” updated incrementally via write barriers every time a reference field is written, using a coarse card table (the heap divided into small fixed-size "cards"; a write marks its card dirty) to keep the bookkeeping cheap. A collection then only needs to scan the RSets of the regions actually being collected, not the whole heap β€” this is the mechanism that makes G1's pause time roughly proportional to the collection set size, not total heap size, which is exactly what makes a soft MaxGCPauseMillis target achievable on multi-hundred-gigabyte heaps in the first place.

"To-space exhausted" precisely means G1 ran out of empty regions to evacuate live objects into, mid-collection. A G1 collection works by copying every live object out of the regions being reclaimed into fresh, empty regions (the "to-space") β€” it's a copying collector, not a mark-and-sweep-in-place one. If the heap's free regions run out during that copy (the live set turned out bigger than G1 predicted, often because of a burst of humongous allocations eating into the free-region pool), G1 can't safely stop partway through an evacuation, so it falls back to a full, single-threaded, stop-the-world garbage collection of the entire heap to recover β€” by far the most expensive pause type G1 can produce, and precisely why the whatIf case above (humongous allocations correlating with to-space exhaustion) is a real production failure mode, not just a log-noise curiosity.

⌨️Hands-on Keyboard

Learn by Doing

bash
# Set a pause target and a larger region size for a large-allocation workload
java -XX:+UseG1GC -XX:MaxGCPauseMillis=150 -XX:G1HeapRegionSize=32m \
     -Xlog:gc*:file=gc.log:time,uptime -jar app.jar

# Grep the log for humongous allocations β€” the tell-tale sign region size is too small:
grep -i humongous gc.log
Output
Fewer/no 'humongous' lines once region size comfortably exceeds 2x the large objects' size.

πŸ”₯What If?

Think Beyond the Expected

Frequent 'humongous allocation' and to-space exhaustion appear in G1 logs β€” what's happening?

Large objects (> half a region) allocate directly into contiguous humongous regions, which fragment and pressure Old gen, triggering costly collections. Fix by increasing -XX:G1HeapRegionSize so those objects aren't humongous, or reducing large allocations.

πŸ˜‚Real World

G1 is the default and usually fine, but big byte[]/buffers triggering humongous allocations is a known tuning gotcha; bumping region size or avoiding giant arrays resolves the GC pressure.

🎯Interviewer's Expectation

Keywords they're listening for:

βœ“ region-based heapβœ“ garbage-first selectionβœ“ pause target drivenβœ“ mixed collectionsβœ“ humongous objects + region size

⚠️Common Mistakes

  • βœ—Allocating huge arrays without considering humongous regions
  • βœ—Treating G1 like a generational copying collector
  • βœ—Setting an unrealistically low pause target

βœ…Best Practices

  • βœ“Tune G1HeapRegionSize for large-object workloads
  • βœ“Set a realistic pause target and measure
  • βœ“Watch for humongous allocations in GC logs

πŸ”Follow-up Questions

  • 1How does MaxGCPauseMillis influence what G1 collects?
  • 2What is a humongous allocation and why is it costly?
  • 3When would you tune G1HeapRegionSize?

🧩Related Technologies

G1HeapRegionSizeMaxGCPauseMillisGC logs

πŸ“šReferences

Continue Learning with AI

Take this question deeper with your favourite AI assistant. Pick a depth, copy the prompt, or open it directly β€” AI is your learning companion, not a shortcut.

Plain-language foundations

I'm preparing for a software engineering interview and want to understand this from scratch, as a beginner.

Topic: Garbage Collection (JVM)
Interview question: "How does G1 GC work internally β€” regions, mixed collections and humongous objects?"

Please:
1. Explain the core idea in simple, plain language, using an everyday analogy.
2. Define any technical terms you use.
3. Walk through one small, concrete example.
4. Finish with a single sentence I can easily remember.

Keep the tone friendly and assume I'm new to this topic.

Was this answer helpful?

Support our platform by exploring our recommended products.

As an Amazon affiliate, purchases through these links may earn us a small commission β€” at no extra cost to you. It helps keep Full Stack Interview Guru free.

Related Questions