A young GC pause stops every Java thread

When main's allocation doesn't fit, it asks for a young collection. Every Java thread stops at a safepoint while GC threads copy the live objects.

Read the explanation
012345678910allocatemain: allocation fails: ask for a GCaskallocateticktickyoung collection at a safepointGC Thread#0: copy live objectscopyGC Thread#1: copy live objectscopy

Tap any block to see what that thread is doing.

  • Running
Step 1/5

Lanes are real JVM threads. main allocates fast; ticker never allocates.

1static byte[][] keep = new byte[1000][]; // live data the collector has to copy2 3public static void main(String[] args) throws Exception {4    AtomicBoolean stop = new AtomicBoolean();5    AtomicLong ticks = new AtomicLong();6    Thread ticker = new Thread(() -> {7        while (!stop.get()) {8            ticks.incrementAndGet(); // never allocates9        }10    }, "ticker");11    ticker.start();12    for (int i = 0; i < 2_000_000; i++) {13        keep[i % 1000] = new byte[1024]; // allocates fast: the young generation fills up14    }15    stop.set(true);16    ticker.join();17    System.out.println("ticker kept ticking: " + (ticks.get() > 0));18}

Explanation

What just happened

main allocated fast, filling G1’s young generation. When the next new byte[1024] didn’t fit, main itself asked for a young collection. The VM Thread brought every Java thread to a safepoint, so main and ticker both stopped. GC worker threads then copied the live objects out of the young generation in parallel, and everyone resumed.

ticker never allocated. It didn’t cause the pause, but it waited for it all the same.

Why it works like this

Copying live objects while other threads change them would be unsafe, so G1 stops every Java thread for the young collection.

Watch out

A pause stops every Java thread, so even code that allocates nothing waits for it. JFR records each one: a jdk.GarbageCollection event named G1New, with cause G1 Evacuation Pause.

Common questions

What triggers a young GC in Java?

An allocation that doesn't fit. The thread whose allocation fails asks the JVM for a young collection, and in this program that is main.

Does a young GC stop all threads?

Yes. G1 runs it at a safepoint on the VM Thread, and every Java thread is stopped until it ends, even ones that never allocate.

Which threads do the garbage collection work in Java?

GC worker threads, named GC Thread#0, GC Thread#1 and so on, copy the live objects in parallel. Your own threads, like main and ticker here, never do that work.

Verified: this timeline matches a real program, checked in CI on JDK 21 and 25. How we verify. Unclear or wrong? Tell us