Memory, Garbage Collection, and Performance
Understand object allocation, garbage collection, reachability, G1 and other collectors, leaks, allocation pressure, profiling, and performance engineering.
Object Lifecycle and Reachability
Java automatically manages object memory. An object becomes eligible for garbage collection when it is no longer reachable from live roots.
Object object = new Object();
object = null;
Setting a variable to null does not force collection. Static fields, thread locals, caches, listeners, and long-lived collections can accidentally retain objects.
A memory leak in a garbage-collected language is usually a logical retention problem rather than failure to manually free memory.
- GC eligibility is based on reachability.
- A garbage-collected application can still leak memory through unintended retention.
- Calling GC explicitly is rarely an appropriate leak fix.
Generational Garbage Collection
Many workloads create short-lived objects. Generational strategies exploit this by treating young and older objects differently.
Allocation
|
v
Young regions
|
| survivors
v
Older regions
|
v
Reclamation / compaction as required
Exact mechanics depend on the collector. Modern collectors such as G1 use regions rather than a simple contiguous physical young/old layout.
The performance question is whether allocation rate, live-set size, collector behavior, and pause characteristics match the application's goals.
- Generational GC exploits object lifetime patterns.
- GC performance depends on allocation rate and live-set characteristics.
- Measure real allocation and pause behavior before tuning.
Modern Collectors: G1, ZGC, and Shenandoah
G1 is a region-based collector designed to balance throughput and pause-time goals. ZGC and Shenandoah emphasize very low pause times through highly concurrent collection techniques.
The correct collector depends on workload, heap size, latency objectives, JVM version, and operational constraints.
java -XX:+UseG1GC -Xms2g -Xmx2g -jar app.jar
For modern JVMs, use the defaults and tuning guidance for the specific JDK release before adding many flags.
GC flags are version- and workload-sensitive. Measure first and consult documentation for the exact JDK release.
- G1 is a common general-purpose collector.
- ZGC and Shenandoah target very low pause behavior.
- Collector tuning must be based on the actual JDK version and workload.
Memory Leaks and Profiling
Common retention sources include unbounded maps, static collections, caches without eviction, listener registrations, thread locals, and accidentally retained object graphs.
static final Map<String, byte[]> cache = new HashMap<>();
void add(String id, byte[] data) {
cache.put(id, data);
}
A heap dump reveals retained memory. Allocation profiling identifies where objects are created rapidly. GC logs and JFR show collection behavior and allocation pressure.
Ask: What is growing? Which objects are retained? Who retains them? Is the growth expected? What is the live set after GC?
- Look at retained size and reference paths, not only object counts.
- Heap dumps answer retention questions; allocation profiling answers creation-rate questions.
- Caches need lifecycle or eviction policies.