Skip to content

JVM and Garbage Collection

Java source is compiled to class files containing bytecode and metadata. A JVM loads, verifies, links, initializes, and executes classes. Interpretation and just-in-time compilation are implementation strategies that preserve observable language and JVM contracts.

Runtime areas

  • each thread has a JVM stack containing frames for active method invocations;
  • objects and arrays are generally allocated in a shared heap;
  • class metadata and runtime structures are managed separately by the JVM;
  • native methods and off-heap buffers can consume memory outside the Java heap.

The specification defines abstract runtime data areas, not one universal memory layout or byte cost.

Reachability and collection

Garbage collectors reclaim objects that are no longer reachable through the collector's root model. Collection time is not deterministic, and finalization is not a resource-management mechanism. Close files, sockets, and other scarce resources explicitly with try-with-resources.

Different collectors optimize goals such as throughput, pause time, footprint, or scalability. A collector does not prevent memory leaks: retaining an unneeded object through a live reference keeps it reachable.

Class initialization

Class initialization has synchronization and happens-before guarantees. It is a safe way to publish static immutable state, but initialization cycles and heavy static work can make behavior difficult to reason about.

Performance reasoning

JIT compilation can inline, specialize, eliminate allocations, and remove dead work when observable behavior is preserved. This is why reading source code and counting allocations is not a substitute for profiling. Likewise, one GC log or heap size is not enough to select a collector.

Use Java Flight Recorder, heap analysis, allocation profiling, GC logs, and JMH according to the question. Measure representative workloads and distinguish latency distributions from throughput. The debugging and profiling guide connects these tools to hypothesis-driven CPU, memory, and concurrency analysis.

Exercises

  1. Explain how a static collection can cause a logical memory leak.
  2. Contrast heap exhaustion with native-memory exhaustion.
  3. Explain why System.gc() is not a resource-lifecycle contract.