Why Minor, Major, and Full GC Aren’t What You Think – A Deep Dive into JVM GC Pauses
This article clarifies the often‑confusing terminology of Minor, Major, and Full garbage collection in the JVM, explains how each type of GC works, analyzes real GC logs with code examples, and advises monitoring latency or throughput rather than relying on those labels.
When working on GC pause detection at Plumbr, the author found confusion around Minor, Major, and Full GC events and wrote this article to clarify.
The article assumes familiarity with the JVM's basic garbage collection principles. The heap is divided into Eden, Survivor, and Tenured/Old spaces; generational assumptions and other GC algorithms are beyond the scope.
Minor GC
Collecting memory from the young generation (Eden and Survivor) is called Minor GC. Key points:
Triggered when the JVM cannot allocate a new object, e.g., Eden is full; higher allocation rate leads to more frequent Minor GC.
When the memory pool is filled, its contents are copied and the write pointer starts at zero, eliminating fragmentation in Eden and Survivor.
Minor GC does not affect the permanent generation; references from the permanent to the young generation are GC roots, while references from young to permanent are ignored during marking.
Contrary to common belief, not every Minor GC causes a stop‑the‑world pause; pauses are noticeable only when many objects survive and need to be copied.
Thus each Minor GC cleans the young generation memory.
Major GC vs Full GC
These terms lack formal definitions in the JVM specification, but generally:
Major GC cleans the old generation.
Full GC cleans the entire heap, both young and old generations.
In practice, many Major GCs are triggered by Minor GCs, and modern collectors may also clean parts of the permanent generation, making the distinction blurry.
Example GC Log
The following excerpt shows GC events captured 17 seconds after JVM start, revealing 12 Minor GCs and 2 Full GCs over a total pause time of about 50 ms.
java -XX:+PrintGCDetails -XX:+UseConcMarkSweepGC eu.plumbr.demo.GarbageProducer 3.157: [GC (Allocation Failure) 3.157: [ParNew: 272640K->34048K(306688K), 0.0844702 secs] 272640K->69574K(2063104K), 0.0845560 secs] [Times: user=0.23 sys=0.03, real=0.09 secs]... (additional log lines omitted for brevity) ...
Detailed GC Phases
Using -XX:+PrintGCDetails provides a more granular view:
Initial marking (≈4 ms) stops all application threads.
Parallel marking and cleaning run concurrently with application threads.
Remark phase (≈46 ms) pauses all threads again.
Concurrent sweeping runs in parallel without stopping threads.
The logs show that only a Major GC was performed to clean the old generation, not two Full GCs.
Conclusion
Rather than categorizing GC events as Minor, Major, or Full, monitor application latency or throughput and correlate those metrics with GC pauses. Determine whether a GC pause stopped all threads or ran concurrently, and use that insight for performance tuning.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
