skip to content

The Garbage-First collector is named for the order in which it reclaims memory. Explain what 'garbage first' means in practice and how the collector chooses which heap regions go into the next collection set.

level: middleimportance: must knowfreq 55%

answer

  1. cost = live bytes, reward = whole region
  2. sort old regions by garbage, take richest first
  3. young regions always in the CSet
  4. liveness comes from the concurrent marking cycle
  5. live threshold 85%, count target spreads mixed GCs

basics

~20 s

G1 tracks how much live data each region holds. For a given pause it collects all young regions plus, in mixed collections, the old regions with the least live data - the most garbage - because evacuation cost scales with live bytes, so those regions give the most free space per millisecond spent.

solid answer

~50 s

G1 collects by copying live objects out of a region and freeing the region whole, so the cost of collecting a region is proportional to its **live** data, while the payoff is the region's **garbage**. Ranking regions by garbage-per-unit-cost and taking the best ones first is what 'garbage first' means. The concurrent marking cycle computes a liveness estimate for every old region. G1 then builds a **collection set** for each pause. Young regions are always included - they cannot be skipped, because G1 does not track references into young regions individually. In a **mixed** collection G1 adds old regions from the sorted candidate list, richest in garbage first, adding regions only while its prediction model says the pause will still fit the pause-time goal. Regions whose live occupancy exceeds a threshold (`-XX:G1MixedGCLiveThresholdPercent`, 85 by default) are not worth evacuating and are skipped. `-XX:G1MixedGCCountTarget` spreads the candidate set over several mixed collections instead of one giant pause.

code

text · 4 lines
text
-XX:MaxGCPauseMillis=200          # soft pause goal; bounds how many old regions fit in a CSet
-XX:G1MixedGCLiveThresholdPercent=85  # skip old regions denser than this in live data
-XX:G1MixedGCCountTarget=8        # spread the candidate old regions over ~8 mixed collections
-XX:G1HeapWastePercent=5          # stop mixed collections once reclaimable heap falls below this

go deeper

for a junior

Know that G1 prefers to collect regions containing the most garbage because copying only the few live objects is cheap.

for a middle

State the cost model (work scales with live data, reward is the whole region), that liveness comes from concurrent marking, and that young regions are always in the collection set.

for a senior

Discuss how the pause goal bounds how many old regions enter each mixed collection, the live-threshold and count-target knobs, and the failure mode when no region is garbage-rich enough.

for a principal

Position it as a scheduling policy over a heterogeneous work queue: profitability-ordered selection under a latency budget, whose degradation path is starvation of reclamation and fallback to a full collection.

## The cost model that gives the collector its name G1 reclaims a region by evacuating it: every live object inside is copied elsewhere, references to it are updated, and then the whole region is returned to the free list. Two facts follow. First, the *work* of collecting a region is proportional to the number of live bytes it contains - copying is the dominant cost, plus the references that must be fixed up. Second, the *reward* is the whole region: the garbage in it costs nothing to reclaim, because nothing is done to dead objects at all. That asymmetry is the entire idea. A region that is 5% live yields 95% of a region of free space for 5% of a region's worth of copying. A region that is 90% live yields almost nothing for almost the full copying cost. So if you must fit collection into a bounded pause, you should sort regions by how much garbage they yield per unit of work and take the best ones first. Hence Garbage-First. ## Where the liveness numbers come from G1 cannot know a region's live data without marking. The concurrent marking cycle traces the object graph while the application runs and, at its end, records a per-region live-bytes figure. Those figures are what the collector sorts on. This is why old regions become collection candidates only after a marking cycle has completed: before that, G1 has no basis on which to rank them. ## Building a collection set Every G1 pause evacuates a **collection set** (CSet), a chosen set of regions: - **Young-only collection**: the CSet is all eden and survivor regions. Young regions are mandatory. G1 keeps remembered sets that record references *into* old regions, not into young ones, so it cannot evacuate some young regions while leaving others behind; the young set goes as a unit. G1 controls cost here by controlling how large the young set is allowed to grow before a pause is triggered. - **Mixed collection**: the CSet is all young regions plus a selection of old candidate regions. G1 walks the candidate list from most garbage to least, adding regions while its pause prediction still fits the target given by `-XX:MaxGCPauseMillis`. Two limits shape it: `G1MixedGCLiveThresholdPercent` (default 85) excludes regions that are too densely live to be worth copying, and `G1MixedGCCountTarget` (default 8) spreads the candidates across several mixed collections so no single pause tries to absorb them all. Since JDK 12, an in-progress mixed collection can also abort part-way if the prediction turns out to be wrong. ## Why the young set is not ranked Candidates for ranking are old regions only. Young regions are typically mostly garbage anyway (the vast majority of objects die young), so collecting all of them is nearly always a good deal - the ranking machinery would add cost without adding much choice. ## What this buys and what it costs The benefit is that old-generation reclamation becomes incremental and steerable: instead of one operation whose cost scales with the whole old generation, G1 performs many bounded operations, each choosing the most profitable work available. The cost is that low-garbage regions may never be selected. If a heap fills with regions that are dense with long-lived data, G1 cannot reclaim enough per pause, allocation outruns reclamation, and the collector falls back to a full collection. That is the failure mode to name when asked what happens when garbage-first selection stops working.

  • Why can G1 not simply pick a subset of young regions the way it picks old ones?
    Because its remembered sets only record references pointing into regions that might be collected independently, and G1 deliberately does not maintain per-region records of references into young regions - that would make the write barrier far more expensive. Without those records it cannot find all roots for a single young region, so the entire young set is evacuated together and cost is controlled by capping young size instead.
  • What happens when every old region is too densely live to be a good candidate?
    Garbage-first selection has nothing profitable to choose, so mixed collections reclaim little. If allocation continues, G1 exhausts free regions and falls back to a full, whole-heap compacting collection, which is exactly the long pause the design was meant to avoid. In practice this shows up as rising heap occupancy after mixed cycles, then a full GC in the log.

Clearing storage lockers where you must personally carry out anything still wanted. You empty the near-empty lockers first: minimum carrying, maximum space freed. The locker packed to the ceiling stays, because emptying it costs a full day and frees the same single locker.

saying these in an interview costs you the question

  • Saying G1 collects the oldest regions first - it collects the emptiest ones first, regardless of age.
  • Claiming G1 can skip individual young regions to shorten a pause.
  • Believing old regions can be ranked before any concurrent marking cycle has completed.
  • Assuming a region that is 100% live is still worth evacuating; G1 deliberately skips dense regions.
  • Treating -XX:MaxGCPauseMillis as a hard limit that selection can always satisfy.

context