Back to JVM Tuning & Troubleshooting
Q3Question 3 of 15

What is the difference between Minor GC and Full GC?

Key Concepts
  • Minor GC: Young Gen only – fast, low pause
  • Full GC: entire heap + metaspace – long pause, stop-the-world
  • Major GC: Old Gen only (G1 uses mixed collections instead)
  • Avoid Full GC in production – tune Young Gen size and promotion threshold
  • Understanding this concept is essential for Java interviews at senior level

Definition

Minor GC cleans the small Young Gen quickly and often; Major/Full GC cleans the Old Gen or whole heap slowly and rarely, with a longer pause.

A Minor GC collects only the Young Generation. It is fast and happens frequently because the Young Generation is small and mostly full of dead objects. A Major GC collects the Old Generation, and a Full GC collects the entire heap including Young Generation, Old Generation, and often cleans up Metaspace. Major and Full GCs are slower and cause longer stop-the-world pauses because they scan a much larger area and may need to compact memory.

Understanding the Concepts

What is Minor GC?

A Minor GC is triggered when Eden fills up. It uses a copying algorithm over the Young Generation only. Because most newly created objects are already dead, the collector copies the small set of survivors into a Survivor space and clears Eden in bulk. This is extremely fast, usually single-digit milliseconds, and it is a stop-the-world event, meaning application threads pause briefly during the copy. Minor GC runs often precisely because the Young Generation is small and allocation is constant.

BASH
# GC log output showing a Minor GC pause
[0.234s][info][gc] GC(0) Pause Young (Normal) (G1 Evacuation Pause) 24M->4M(256M) 2.145ms
#                                                                   ^freed 20M    ^2ms pause

What is Major GC and Full GC?

A Major GC targets the Old Generation. It runs when the Old Generation gets full, typically after many objects have been promoted. A Full GC is broader still: it collects the Young Generation, the Old Generation, and may also reclaim Metaspace and perform heap compaction to remove fragmentation. Both are slower because the Old Generation is usually much larger than the Young Generation, and compaction involves moving live objects and updating references. These pauses can range from tens of milliseconds to seconds depending on heap size and collector.

BASH
# GC log output showing a Full GC – note the much longer pause
[45.678s][info][gc] GC(42) Pause Full (Allocation Failure) 3800M->1200M(4096M) 1842.567ms
#                                                          ^freed 2600M        ^1.8 seconds!

How do they differ?

| Property | Minor GC | Major/Full GC |
|---|---|---|
| Region collected | Young Gen only | Old Gen or entire heap |
| Trigger | Eden full | Old Gen full, or explicit System.gc() |
| Algorithm | Copying (fast) | Mark-sweep-compact (slow) |
| Typical pause | 1-10 ms | 50 ms to several seconds |
| Frequency | Often (seconds to minutes) | Rarely (minutes to hours) |
| Stop-the-world | Yes (brief) | Yes (long) |

What do modern collectors do differently?

The terms overlap in practice. In older collectors a "Full GC" meant a single-threaded, stop-the-world collection of everything. Modern collectors like G1 try to avoid Full GC entirely by doing concurrent marking and incremental "mixed" collections that clean some Old Gen regions alongside the Young Gen, keeping pauses short. A Full GC in G1 is treated as a failure mode you want to avoid, often caused by the heap being too small or allocation outpacing collection.

JAVA
package com.bank.monitoring;

// In a banking service, monitor GC behavior to catch problems early
public class GCHealthCheck {
    public static void main(String[] args) {
        // Never call System.gc() in production – it triggers a Full GC
        // System.gc();  // BAD: forces expensive Full GC

        // Instead, monitor GC via JMX or GC logs
        java.lang.management.GarbageCollectorMXBean gc =
            java.lang.management.ManagementFactory.getGarbageCollectorMXBeans().get(0);
        System.out.println("GC name: " + gc.getName());
        System.out.println("Collection count: " + gc.getCollectionCount());
        System.out.println("Collection time: " + gc.getCollectionTime() + " ms");
    }
}

What are the warning signs?

Frequent Minor GCs with short pauses are healthy. Frequent Full GCs are a red flag, often signaling a memory leak, an undersized heap, or premature promotion. A senior engineer reads GC logs and watches two numbers: pause time per collection and total time spent in GC. If Full GCs are frequent and long, the application spends more time collecting garbage than doing work.

BASH
# Enable GC logging (Java 9+)
java -Xlog:gc*:file=gc.log:time,level,tags -Xmx4g -jar bank-app.jar

# Quick check: is GC dominating?
jstat -gcutil <pid> 1000
# Watch the GCT (total GC time) and FGC (Full GC count) columns

In banking applications at National Bank of India, Rajesh alerts when Full GC count exceeds zero per hour in steady state, because a single Full GC can cause a multi-second pause that blocks customer transfers.

Key Takeaway

A Minor GC collects only the Young Generation. It runs frequently because the Young Generation is small and fills up fast, but each collection is very quick, usually just a few milliseconds, because most of the objects there are already dead and the collector only has to copy the small number of survivors. A Major GC collects the Old Generation, and a Full GC collects the entire heap including both generations and often Metaspace too. These are much slower because the Old Generation is large and the collector may need to compact memory by moving live objects and fixing their references, which produces a longer stop-the-world pause.

The practical difference is what each one tells you about the health of your application. Frequent Minor GCs with short pauses are completely normal and healthy. Frequent or long Full GCs are a warning sign. They usually mean one of three things: the heap is too small, there is a memory leak where objects are never released, or there is premature promotion where short-lived objects are wrongly ending up in the Old Generation. Modern collectors like G1 work hard to avoid Full GCs entirely by collecting the Old Generation incrementally and concurrently, so when I see a true Full GC in a G1 log I treat it as a problem to investigate.

In my banking work at National Bank of India, I read GC logs as a routine part of production monitoring. During peak trading our order service produces a storm of short-lived objects, so I expect to see many Minor GCs, and as long as each is a few milliseconds I know we are fine. The moment I saw Full GCs appearing every few minutes with pauses of hundreds of milliseconds, I knew something was wrong, and it turned out to be an unbounded cache that was never evicting entries, slowly filling the Old Generation. I fixed it by putting a size limit and time-to-live on the cache, and the Full GCs disappeared. That is why I always alert on Full GC frequency and total GC time percentage, because a healthy service spends almost all its time serving customers and almost none collecting garbage.

Remember one sentence: What is the difference between Minor GC (collects Young Gen, fast, frequent) and Major/Full GC (collects entire heap including Old Gen, slow, causes longer pause) is fundamental knowledge for Java interviews and production banking work.

---

Share
Use ← → arrow keys to navigate