In Lesson 23, an old Customer kept a young Order alive. Remembered information gave the collector an incoming reference without searching every old object. What does a collector do with that information when it must recover space repeatedly, while old objects also accumulate?
On normal JDK 25 server-class configurations, the default collector is G1, or Garbage-First. G1 divides the heap into regions and selects a Collection Set (CSet) of source regions for each evacuation pause. It copies reachable objects out and makes successfully evacuated source regions reusable. The choice of old regions later in the cycle uses liveness and predicted cost.
Regions are G1’s units of space management; the Collection Set defines the source regions a pause will evacuate.
Generation roles on a regional heap
Each G1 region is an equally sized contiguous range of virtual heap memory. Eden, Survivor, and Old are roles assigned to regions. A heap can therefore have an Eden region beside an Old region, with a free region elsewhere. The generations remain useful logical groups, but they do not require three fixed, contiguous address partitions.
For example, a free region can become Eden when allocation needs space. After a successful young collection moves its survivors away, that same source region becomes free again. G1 can later assign it another role. This flexibility lets the young and old portions of the heap adapt without moving a permanent boundary between them.
One young evacuation, from roots to free regions
Imagine two Eden regions in the CSet. The first contains live objects A and B among dead objects; the second contains live C. G1 must identify all three survivors, including any reached from outside the CSet. VM and thread roots, code roots, and remembered references from other heap regions provide starting points. A remembered set records approximate outside locations, typically cards, that may contain references into selected regions. The collector scans the relevant locations; they are not a perfect list of individual pointers.
During the stop-the-world young pause, G1 follows those roots, copies live young objects to Survivor or Old destination regions according to age and policy, and updates references to the moved objects. Dead objects stay in the source regions. Once evacuation succeeds, the complete source regions are available for reuse.
This is reclamation and compaction at region granularity: destinations hold copied survivors, and successfully emptied source regions have no holes to manage. Normal G1 evacuation still pauses application threads, even though a different part of G1’s cycle performs marking concurrently.
Why old liveness must be measured
Young collections remove short-lived objects, but survivors may promote. Old regions then contain a mix of retained objects and objects that later become unreachable. Occupancy alone cannot tell G1 how much useful space an old region would yield: a nearly full region could be almost entirely live or mostly garbage.
G1 therefore runs a broader liveness analysis before choosing old regions. At a high level its cycle moves through a Young-Only phase, a Concurrent Start young pause, Concurrent Mark, Remark, Cleanup, and a Space-Reclamation phase with Mixed collections. Normal young collections can also occur while marking is in progress; the diagram simplifies that overlap.
Concurrent Start starts marking as part of a young collection. Concurrent Mark traces liveness while application threads continue changing references. Remark and Cleanup are stop-the-world pauses that finish the marking transition and prepare the next phase. Older descriptions may call the initiating work “Initial Mark”; Concurrent Start is the current JDK 25 phase name used here.
Concurrent tracing needs a stable logical view even though the physical object graph changes. G1 uses snapshot-at-the-beginning (SATB): objects live at the start of marking are treated as live for that cycle, which can conservatively defer some reclamation. Lesson 25’s SATB walkthrough will trace the pre-write barrier that preserves this view. Here the key result is old-region liveness information, not the barrier mechanics.
Choosing old regions by useful reclamation
Suppose one old region is 90% live and another is 15% live. Copying the first would move much more data for little recovered space; the second looks more promising. Marking supplies the liveness estimate that makes this comparison possible.
“Garbage-First” means G1 tries to spend pause time where reclamation is efficient. Candidate evaluation also considers predicted evacuation cost, root and remembered-set work, connectivity between regions, available pause budget, and reclamation goals. A simple sort by garbage percentage would miss those costs.
G1 chooses old-region work for useful reclaimed space relative to its predicted collection cost.
Mixed collections spread old reclamation across pauses
In the Space-Reclamation phase, a Mixed collection includes the required young regions plus selected old candidates in its CSet. Young survivors move to Survivor or Old destinations; live objects from selected Old source regions move to other Old destinations. Successfully evacuated sources become reusable. G1 distributes old work over multiple mixed pauses instead of placing every old candidate in one pause.
G1 uses observations from earlier pauses to predict work when sizing a CSet. Required young work, incoming-root scanning, object copying, and optional old-region work all consume the budget. Larger live-data volume or more cross-region references can change the estimate even when region count looks similar.
Special paths and production evidence
Humongous objects receive special treatment: objects at least half a region in size are allocated directly into old-generation humongous regions, potentially spanning multiple regions. They generally do not follow the ordinary Eden-to-Survivor evacuation path, and G1 normally reclaims their regions after determining they are dead rather than moving them during ordinary collections.
Evacuation also needs destination space. If G1 cannot find enough room for live objects during a pause, evacuation failure can leave some objects in place and add recovery work. If memory pressure becomes severe while liveness information is being gathered, G1 may fall back to a stop-the-world Full GC. Heap headroom therefore matters alongside occupancy and the pause target.
Start with unified logging:
-Xlog:gc*
For a deeper pause breakdown, add -Xlog:gc+phases=debug; for CSet selection details, use -Xlog:gc+ergo+cset=debug. The phase log exposes categories such as Object Copy, Ext Root Scanning, Code Root Scan, and Scan Heap Roots. Read these as evidence from a particular run, not fixed costs for every G1 workload.
Check your reasoning
An old object outside the CSet points to a young object inside it. Which information lets G1 find that survivor?
VM and thread roots alone may miss it. Remembered information identifies outside card locations that may contain references into the CSet; scanning them supplies the incoming edge for evacuation.
Two old regions each occupy one region. One is 90% live and one is 15% live. Why might G1 prefer the second, and what else affects the choice?
It likely yields more free space with less live-object copying. Predicted evacuation and root/remembered-set cost, connectivity, pause budget, and reclamation goals also matter.
Concurrent Mark is running. Does that mean a young or Mixed evacuation can proceed while application threads run?
No. Marking has a concurrent phase, but normal G1 evacuation remains stop-the-world. Concurrent Start, Remark, Cleanup, and evacuation pauses stop application threads for their respective work.
What this adds to the GC model
The regional heap lets G1 reuse source regions after evacuation. Remembered roots make a CSet safe to collect; concurrent marking finds promising old candidates; mixed pauses add a measured portion of those candidates to young work. Together, they explain how G1 pursues useful reclamation while controlling ordinary pause work.
The next lesson will examine how SATB keeps concurrent marking correct when an application overwrites references, and what the pre-write barrier and Remark phase contribute.
Sources and implementation boundaries
Based on Daily JVM Byte #24 and its reviewed draft. Object names, region fractions, and figures are illustrative; no GC workload was run for this lesson. Collector behavior and logging refer to HotSpot G1 in JDK 25, not Java language guarantees or every JVM implementation. Scheduling, CSet choices, and measured pause costs vary by workload and configuration.