Fundamentals 22 min read

Why Does Thread.sleep(0) Appear in RocketMQ Code? Uncovering the Safepoint Trick

The article investigates a mysterious "prevent gc" comment in RocketMQ's source, explains how Thread.sleep(0) forces a JVM safepoint to mitigate long GC pauses, and demonstrates that changing loop counters from int to long eliminates the need for the hack.

ITPUB
ITPUB
ITPUB
Why Does Thread.sleep(0) Appear in RocketMQ Code? Uncovering the Safepoint Trick

This article starts from a puzzling comment "prevent gc" found in a RocketMQ source file and asks why a seemingly useless Thread.sleep(0) call is placed inside a for‑loop that runs millions of times.

Observation

The loop uses an int counter j and, every 1000 iterations, executes an if block whose only statement is Thread.sleep(0). The original author could not find any explicit explanation in the commit history.

Thread.sleep(0);

The comment translates to "prevent GC thread from performing garbage collection".

Hypothesis and Theory

Based on JVM internals, the author hypothesizes that the code is intended to create a safepoint so that the GC thread gets a chance to run, thereby avoiding long stop‑the‑world pauses. This is related to the concept of safepoint and counted loops in HotSpot.

In HotSpot, loops that use small integer types (called counted loops ) are optimized to omit safepoint checks until the loop finishes. Changing the loop counter to a long (an uncounted loop ) forces the JVM to insert safepoint polls inside the loop.

Evidence from Documentation

Quotes from "Deep Understanding of the JVM" describe how safepoints work: a thread can only be paused for GC at a safepoint, and counted loops may delay reaching a safepoint.

"With the safepoint mechanism, the JVM can only pause a user thread at a safepoint, not at arbitrary bytecode positions. Counted loops (int index) may skip safepoint checks until the loop ends."

Further evidence from OpenJDK source ( safepoint.cpp) shows that returning from a native method (such as Thread.sleep) triggers a safepoint check.

When returning from native code, a Java thread must check the safepoint state to see if it must block.

Practical Experiment

A test program creates two long‑running loops (using int) and sleeps the main thread for 1 s. The main thread does not resume until both loops finish, confirming that the GC safepoint cannot be reached while the counted loops run.

public class MainTest {
    public static AtomicInteger num = new AtomicInteger(0);
    public static void main(String[] args) throws InterruptedException {
        Runnable runnable = () -> {
            for (int i = 0; i < 1000000000; i++) {
                num.getAndAdd(1);
            }
            System.out.println(Thread.currentThread().getName() + " execution finished!");
        };
        Thread t1 = new Thread(runnable);
        Thread t2 = new Thread(runnable);
        t1.start();
        t2.start();
        Thread.sleep(1000);
        System.out.println("num = " + num);
    }
}

When the loop counter is changed to long, the program proceeds as expected, demonstrating that the loop becomes an uncounted loop and safepoint polls are inserted.

Conclusion

The mysterious Thread.sleep(0) is a deliberate trick to force a safepoint inside a counted loop, preventing the GC thread from being blocked for a long time. Replacing the int counter with long achieves the same effect without the confusing native call.

In summary, the "prevent gc" comment hides a clever use of Thread.sleep(0) to create a safepoint inside a counted loop, thereby reducing the latency of GC pauses; converting the loop counter to

long> makes the safepoint implicit and removes the need for the hack.
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaJVMSafepointRocketMQgcthread-sleepCounted Loop
ITPUB
Written by

ITPUB

Official ITPUB account sharing technical insights, community news, and exciting events.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.