Understanding JVM GC Algorithms and the Generational Model
This article explains the three fundamental garbage‑collection algorithms (Mark‑Sweep, Copying, Mark‑Compact), the three generational hypotheses, the structure and rules of the young generation, the distinctions among Minor, Major and Full GCs, and how remembered sets and card tables efficiently handle cross‑generation references in the JVM.
1. Three Basic Algorithms: Mark‑Sweep, Copying, Mark‑Compact
After determining which objects are dead, the JVM must reclaim their memory. Historically three core algorithms are used, and all modern collectors are combinations or variants of them.
Mark‑Sweep – Mark reachable objects, then sweep away the rest. It is simple but suffers from unstable performance when many objects are reclaimed and creates memory fragmentation because freed spaces are non‑contiguous.
Efficiency not stable : both marking and sweeping time grow with the number of objects.
Memory fragmentation : freed slots are scattered, preventing allocation of large objects despite enough total free memory.
Copying – Divide the heap into two halves; live objects are copied from the active half to the other, then the former half is cleared.
Advantages : no fragmentation; allocation is a simple pointer bump.
Disadvantages : only half of the memory is usable at any time.
Copying is suitable when the survival rate is low, which matches the characteristics of the young generation.
Mark‑Compact – Similar to Mark‑Sweep’s marking phase, but instead of sweeping, live objects are moved to one end of the heap and the remaining space is reclaimed in one contiguous block.
Advantages : eliminates fragmentation.
Disadvantages : moving objects is costly and requires a stop‑the‑world pause.
Mark‑Compact fits the old generation where survival rates are high.
One‑sentence comparison : Mark‑Sweep fragments, Copying wastes half the space, Mark‑Compact costs time – therefore the JVM applies each algorithm where its strengths match the object’s age.
2. Generational Hypotheses
Weak generational hypothesis : Most objects die young ("short‑lived").
Strong generational hypothesis : Objects that survive many GCs become harder to collect.
Cross‑generation reference hypothesis : References from old to young objects are rare.
These hypotheses lead to a design that partitions the heap by object age: young objects go to the Young Generation, which is collected frequently with the Copying algorithm; long‑lived objects reside in the Old Generation, collected infrequently with Mark‑Compact (or Mark‑Sweep).
3. Structure of the Young Generation: Eden and Two Survivors
The Young Generation is split into three spaces: a large Eden area and two equal Survivor spaces (S0 and S1) with a default ratio of 8:1:1, controlled by -XX:SurvivorRatio=8.
Normally Eden and one Survivor are active (≈90% of the young space); the other Survivor stays idle.
When a Minor GC occurs, live objects in Eden and the active Survivor are copied to the idle Survivor, then Eden and the previously active Survivor are cleared.
After each GC the roles of the two Survivors swap.
This design reduces the “wasted” space to a single idle Survivor (≈10%) instead of the 50% waste of a naïve Copying algorithm.
If the surviving objects exceed the idle Survivor’s capacity, the excess is promoted directly to the Old Generation (the “allocation guarantee” mechanism described later).
4. Object Movement Rules
Rule 1 – Eden first : New objects are allocated in Eden; when Eden fills, a Minor GC is triggered.
Rule 2 – Large objects : Objects exceeding a size threshold (set by -XX:PretenureSizeThreshold) are allocated directly in the Old Generation to avoid costly copying.
Rule 3 – Tenuring : Each object has an age counter; after surviving a Minor GC the age increments. When the age reaches the default threshold of 15 (controlled by -XX:MaxTenuringThreshold), the object is promoted to the Old Generation.
Rule 4 – Dynamic age determination : If objects of a certain age occupy more than half of a Survivor’s space, all objects of that age or older are promoted early, bypassing the fixed age limit.
Rule 5 – Allocation guarantee : Before a Minor GC, the JVM checks whether the Old Generation has enough contiguous space for possible promotions; if not, a Full GC may be triggered.
The typical life‑cycle of an object is: allocated in Eden → survives Minor GCs and moves between Survivors while aging → promoted to Old Generation when age criteria are met → very large objects skip the young generation entirely.
5. GC Types: Minor, Major, Full, Mixed
Minor GC (Young GC) : Collects only the Young Generation; very frequent and fast (milliseconds).
Major GC (Old GC) : Collects only the Old Generation; currently only the CMS collector performs this.
Full GC : Collects the entire heap and the method area; slow, stop‑the‑world pauses can reach hundreds of milliseconds or seconds, making it the primary target of performance tuning.
Mixed GC : Specific to G1; collects the whole Young Generation plus a part of the Old Generation.
In practice, developers focus on minimizing Full GC pauses because they freeze the application.
Common triggers for Full GC include Old Generation space shortage, Metaspace exhaustion, allocation‑guarantee failure before a Minor GC, and explicit calls to System.gc() (strongly discouraged).
6. Cross‑Generation References: Remembered Set and Card Table
During a Minor GC the JVM must also consider references from Old to Young objects; otherwise a live young object could be mistakenly reclaimed.
Scanning the entire Old Generation each time would defeat the speed goal of Minor GCs. Because cross‑generation references are rare (hypothesis 3), the JVM records only the locations in the Old Generation that contain such references.
This record is the Remembered Set , typically implemented as a Card Table :
The Old Generation is divided into fixed‑size card pages (usually 512 bytes).
A byte array (the card table) maps each card page to a state.
If a card page contains a reference to the Young Generation, the corresponding entry is marked “dirty”.
During Minor GC, only dirty cards are scanned, dramatically reducing work.
Dirty marks are set by a write barrier : each time a field that holds an object reference is written, the JVM inserts a small piece of code that checks whether the write creates a cross‑generation reference and, if so, marks the relevant card as dirty.
Note: This write barrier is unrelated to the memory barriers used for concurrency control (e.g., volatile ).
The combination of Remembered Set, Card Table, and write barrier is essential for the efficiency of generational collection.
7. Summary
Three basic algorithms each have trade‑offs: Mark‑Sweep (fragmentation), Copying (half‑space waste, good for low survival), Mark‑Compact (time‑consuming, good for high survival).
Generational hypotheses drive the division of the heap into Young (Copying, frequent) and Old (Mark‑Compact, infrequent) generations.
Young Generation layout: Eden : S0 : S1 = 8 : 1 : 1, keeping one Survivor idle to limit waste to ~10%.
Object movement follows five rules: Eden first, large objects to Old, tenuring at age 15 (limited by a 4‑bit age field), dynamic age promotion, and allocation guarantee.
GC classifications: Minor GC (fast, young only) vs. Full GC (slow, whole heap, primary tuning target).
Cross‑generation references are handled by Remembered Set / Card Table plus write barriers, avoiding full Old‑generation scans.
The next article will map these concepts to concrete collectors such as Serial, Parallel, CMS, and G1, and discuss the differences between JDK 8 and JDK 17.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
