Detailed explanation
Garbage collection (GC) is Java’s automatic mechanism for reclaiming heap memory occupied by objects that are no longer reachable. It reduces the need for manual memory allocation and deallocation, helping developers avoid errors such as double-freeing memory. However, GC does not prevent every memory problem: an application can still retain unwanted objects or exhaust its heap. Interviewers expect you to distinguish between an object becoming eligible for collection and its memory actually being reclaimed; these events need not happen immediately together.
The JVM determines reachability by tracing references from GC roots, such as references in active thread stacks, static fields of reachable classes, and JNI references. Objects reachable through these reference chains remain live. Objects outside those chains may be reclaimed, even if they reference one another, so unreachable cycles are collectible. For example, after `Person p = new Person(); p = null;`, the newly created object becomes eligible for GC only if no other reachable reference to it exists. Setting a variable to null removes that reference; it does not directly delete the object.
Many collectors use generations because most objects tend to become unreachable relatively quickly. In a typical generational layout, new objects enter the young generation, and surviving objects may eventually move to the old generation. Metaspace is not another heap generation: it uses native memory for class metadata, which can be reclaimed when classes are unloaded. Collector strategies include tracing, copying, marking, sweeping, and compaction. Parallel GC emphasises throughput, G1 organises the heap into regions to support pause-time goals, and ZGC emphasises low pauses through largely concurrent work. Collector behaviour and defaults depend on the JDK version.
GC matters because its CPU consumption, memory requirements, and pauses affect application performance. Some work requires stop-the-world pauses, while concurrent collectors perform much of their work alongside application threads. `System.gc()` requests collection but does not guarantee that the JVM will perform it or reclaim a particular object. Finally, GC manages memory, not timely cleanup of files, sockets, or database connections; use explicit closing, preferably through try-with-resources, for those resources.
Key points to remember
- GC reclaims heap memory based on reachability, not merely whether a variable goes out of scope.
- Unreachable reference cycles are collectible; collection eligibility does not imply immediate reclamation.
- Young and old are heap generations; Metaspace holds class metadata in native memory.
- Parallel GC, G1, and ZGC offer different throughput, latency, and memory trade-offs.
- System.gc() is a request, not a guarantee; external resources require explicit cleanup.
Common mistakes candidates make
- Saying that assigning null immediately destroys an object, without checking for other references.
- Describing Metaspace as a third heap generation or assuming every collector has the same layout.
- Assuming GC prevents memory leaks or reliably closes files and database connections.
Likely follow-up questions
Can a Java application have a memory leak despite garbage collection?
Yes. Objects that are no longer useful can remain reachable through static collections, unbounded caches, or forgotten listeners. GC cannot reclaim them while those reference chains remain live.
What is the difference between young-generation and old-generation collection?
Young-generation collection targets an area where many short-lived objects become unreachable, often making reclamation efficient. Old-generation collection handles longer-lived objects, but its scope, frequency, and pause behaviour depend on the collector.
How would you investigate excessive GC activity?
Inspect GC logs for collection frequency, pause durations, allocation rate, and heap occupancy after collection. Use Java Flight Recorder or heap-analysis tools to identify allocation hotspots or retained objects before changing collector or heap settings.
Interview tip: Define GC through reachability, explain the null-assignment example with an aliasing caveat, and finish with collector trade-offs and the limits of System.gc().
