Safepoints and stop-the-world pauses
A pause cannot begin until every thread has reached a point where its state can be read.
Open this lesson in the learning hubKey points
- A safepoint is a place where a thread has published a consistent view of its stack and registers, so the VM can inspect it.
- GC pauses, heap dumps, class redefinition, deoptimisation and most
jcmdcommands all need a global safepoint first. - Threads get there by polling: the JIT plants a cheap check at method returns and loop back-edges, and the thread stops there.
- A long counted
intloop may carry no poll at all, so one thread can keep every other thread waiting to start. - Time to safepoint is separate from the pause itself, and
-Xlog:safepointprints the two numbers side by side. - If pauses look bad but the GC work is small, read the reaching-safepoint time before you touch a single GC flag.
Example
# every stop-the-world pause is two numbers, not one
java -Xlog:safepoint -jar app.jar
# [12.418s][info][safepoint] Safepoint "G1CollectForAllocation", Time since last: 812 ms,
# Reaching safepoint: 0.0421 ms, At safepoint: 6.3110 ms
# ^ waiting ^ the actual GC work
# find the thread that will not poll
java -XX:+SafepointTimeout -XX:SafepointTimeoutDelay=500 -Xlog:safepoint+stats -jar app.jar
# "# SafepointSynchronize::begin: Timeout detected" then names the guilty thread
# JFR records the same thing, as SafepointBegin / SafepointEnd events
jcmd <pid> JFR.start settings=profile duration=30s filename=/tmp/sp.jfr
A pause is the wait for the slowest thread plus the work itself.
This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the JVM course, and every lesson in it is listed on the JVM contents page.