The JVM Specification requires automatic storage management but does not prescribe a collector or heap layout. Collector behavior is therefore a property of the deployed JVM, release, flags, heap size, and workload.
Reachability and Memory Pools #
Tracing begins from GC roots, including live thread stacks and registers,
static fields, JNI handles, and VM runtime structures. An object strongly
reachable from a root remains live. Soft references may be cleared under
memory pressure, weak references do not retain their referents, and phantom
references support post-mortem coordination through ReferenceQueue. None is
a substitute for deterministic resource cleanup; use try-with-resources and
Cleaner only as a safety net. Finalization is deprecated for removal.
The Java heap stores objects and arrays. In HotSpot, metaspace, code cache,
thread stacks, direct buffers, GC bookkeeping, and native libraries consume
memory outside the heap. -Xmx bounds only the Java heap, so container limits
must reserve native headroom. Pool names and accounting are collector and
implementation dependent.
Generations and Allocation #
Generational collectors exploit the fact that many allocations die quickly. New objects are allocated in young regions; survivors can move through survivor spaces and be promoted into old regions. To avoid scanning all old objects for each young collection, write barriers record old-to-young pointers in card tables or remembered sets. Allocation rate, live-set size, promotion rate, and available evacuation space predict pressure better than heap occupancy alone.
HotSpot Collector Trade-Offs #
HotSpot offers collectors with different objectives:
- Serial minimizes implementation overhead for small heaps.
- Parallel prioritizes throughput with parallel stop-the-world work.
- G1 partitions the heap into regions and works toward pause-time goals while balancing concurrent and evacuation work.
- ZGC performs most marking and relocation concurrently to target low pauses at the cost of barriers and concurrent resource use.
- Shenandoah, when the selected distribution supplies it, also performs concurrent evacuation to reduce pause duration.
Collector availability and defaults change by JDK vendor and release. Inspect
the deployed runtime with java -XX:+PrintCommandLineFlags -version and its
release documentation instead of encoding historical defaults into operations
guidance.
All tracing collectors need coordination points. Root processing, remarking, and some evacuation work can stop application threads (STW). Concurrent phases reduce pause time but consume CPU and memory bandwidth, require barriers, and need free space for relocation. A lower pause target can therefore reduce throughput or fail under allocation pressure.
Evidence-Led Tuning #
Enable unified logging and correlate it with application latency and resource metrics:
java -Xlog:gc*,safepoint:file=gc.log:time,uptime,level,tags ...
java -XX:StartFlightRecording=filename=recording.jfr ...Use JFR allocation events, jcmd, heap dumps where retention is suspected,
and CPU/container metrics to distinguish excessive allocation, a growing live
set, fragmentation, and native-memory exhaustion. Tune in order:
- eliminate unintended retention and allocation hot spots;
- size the heap for the measured live set and allocation bursts;
- choose a collector for the measured latency and throughput objective;
- change a small number of documented goals; then
- repeat representative load measurement.
System.gc() is a request, not a correctness mechanism, and can introduce
disruptive work. Application behavior must not depend on collection timing.
Comments
Read or comment on GitHub (sign-in required to comment)