Heap Regions & Generations
The JVM heap is divided into generations: Young Generation (newly allocated objects), Old Generation (long-lived objects), and Metaspace (class metadata, off-heap since Java 8). Young is further split into Eden and two Survivor spaces (S0, S1).
Heap = a nursery (Young) and retirement home (Old). New objects are born in the nursery (Eden). Survivors graduate through toddler rooms (Survivor spaces). Only the toughest make it to the retirement home. Metaspace is the staff office -- outside the building.
Minor GC (Young GC): collects Eden and one Survivor; surviving objects are copied to the other Survivor (incrementing age). Objects that survive a threshold number of minor GCs (default 15) are promoted to Old Generation. Major/Full GC: collects Old Generation (and possibly Young) — much more expensive. Generational hypothesis: most objects die young (short-lived) — this is why the generational split improves GC efficiency. Stack allocation (JIT escape analysis) avoids heap allocation entirely for some short-lived objects.
G1 GC abandons fixed contiguous Young/Old regions — the heap is divided into equal-sized regions (~1-32MB each) and each region is dynamically assigned as Eden, Survivor, Old, or Humongous (for objects > region size / 2). G1 tracks per-region liveness and collects the most garbage-dense regions first (hence 'Garbage First'). Humongous objects are allocated directly in Old Generation and can cause premature Full GC. JVM ergonomics automatically tuned heap sizing (InitialHeapSize, MaxHeapSize) based on physical RAM until Java 8; Docker containers require -XX:+UseContainerSupport (default Java 10+) to read cgroup memory limits instead of host RAM.
The heap has Young Generation (Eden + two Survivors) for new objects and Old Generation for long-lived ones. Minor GC uses stop-the-world copying within Young — fast and frequent. Major/Full GC is slower and stops all threads longer. Objects are promoted to Old after surviving multiple minor GCs (threshold configurable, default 15). In G1, the heap is equal-sized regions dynamically assigned to generations — G1 targets a configurable pause time by selecting the highest-garbage regions to collect first.
Allocating many large objects (> half a G1 region) places them as Humongous objects in Old Generation, bypassing Young GC entirely — they accumulate until a Full GC, causing unexpected long pauses.