HomeBytesheetsRoadmapsUI TemplatesUI ToolsStack Discussion
4 Topics
Chapter•100 Minutes

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.

Key Takeaways
  • 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.

Key Takeaways
  • 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.

Avoid cargo-cult JVM flags

GC flags are version- and workload-sensitive. Measure first and consult documentation for the exact JDK release.

Key Takeaways
  • 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?

Key Takeaways
  • 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.