Что такое stop-the-world?
JVM использует polling page (страницу памяти) вместо флагового check, потому что чтение из кэша (страница почти всегда в L1) быстрее, чем ветвление (branch). Это «fast path» — п...
🟢 Junior Level
Stop-The-World (STW) — это когда JVM останавливает все потоки приложения для выполнения GC.
Простая аналогия: Представьте, что вы работаете в офисе, и вдруг объявляют эвакуацию. Все останавливаются и ждут, пока проверка закончится.
Зачем нужен STW:
- GC — нужно консистентное состояние памяти (объекты не перемещаются во время обхода)
- Не-GC операции: thread dumps, biased lock revocation, class redefinition (JVM TI)
Как долго:
- ZGC: < 1 мс
- G1: 20-200 мс
- Full GC: секунды
🟡 Middle Level
Safepoints
Потоки не могут остановиться мгновенно!
→ Должны дойти до Safepoint (точка остановки)
Где расставлены:
- Перед выходом из метода
- В концах циклов
- Перед вызовами методов
Механизм: Safepoint Poll
→ JVM помечает страницу как недоступную
→ Поток читает → SIGSEGV → переходит в ожидание
TTSP (Time To Safepoint)
Время от команды "стоп" до последнего остановленного потока
Проблемы:
- Counted Loops (циклы int) → могут не иметь Safepoints
- Массивный I/O → поток в системном вызове
- Свопинг → страница Safepoint в swap
Решение: -XX:+UseCountedLoopSafepoints
Thread-Local Handshakes (Java 11+)
Раньше: остановить ВСЕ потоки для операции над одним
Теперь: Handshake с конкретным потоком
→ Остальные работают!
→ Примеры: Thread Dump, Biased Lock отзыв
Диагностика
# Логи Safepoints
-Xlog:safepoint
-Xlog:safepoint+stats
# Ищите:
# "reaching safepoint" → время ожидания
# Если > 100 мс → проблема!
🔴 Senior Level
Safepoint Polling Mechanics
Safepoint Page:
Normal: страница доступна → чтение мгновенно
STW: Guard Page → SIGSEGV → поток в ожидании
JIT вставляет проверку в каждый Safepoint:
movl r0, [safepoint_page] // Fast Path
→ Если страница недоступна → trap
JVM использует polling page (страницу памяти) вместо флагового check, потому что чтение из кэша (страница почти всегда в L1) быстрее, чем ветвление (branch). Это «fast path» — почти нулевой overhead.
Counted Loops Problem
// ❌ JIT не вставляет Safepoints в counted loops
for (int i = 0; i < 1_000_000_000; i++) {
// Миллиард итераций без проверки!
// GC ждёт → TTSP = секунды
}
// Решение:
-XX:+UseCountedLoopSafepoints
// → JIT вставляет проверки каждые N итераций
// → overhead ~1-2%
JNI и STW
JNI-потоки: JVM не может инспектировать их стек во время STW.
JVM ждёт, пока JNI-поток вернётся в Java-код (достигнет safepoint).
JNI-поток не «работает во время STW» — он заблокирован при попытке вернуться в Java.
JFR Safepoint Events
Java Flight Recorder:
→ Событие 'Safepoint Begin'
→ Время: entering + waiting + cleanup
→ Визуализация в JMC
Поиск проблем:
→ Если entering > 50 мс → проблема с TTSP
→ Если waiting > entering → один поток тормозит
Best Practices
- Мониторьте TTSP через safepoint логи
- Counted Loops → UseCountedLoopSafepoints
- Handshakes (Java 11+) → меньше STW
- JFR для визуализации
- Избегайте длинных циклов без Safepoints
- JNI → следите за временем в native
Резюме для Senior
- STW = не только GC, но и другие операции JVM
- Safepoints = механизм координации потоков
- TTSP = время входа в STW (может быть > самого GC!)
- Counted Loops = частая причина длинных TTSP
- Handshakes (Java 11+) = снижение глобальных пауз
- JFR = лучший инструмент для анализа
🎯 Шпаргалка для интервью
Обязательно знать:
- STW — JVM останавливает ВСЕ потоки приложения; не только для GC, но и для thread dumps, biased lock revocation, class redefinition
- Safepoints — точки в коде (выход из метода, конец цикла), где поток может остановиться; механизм: Safepoint Poll ( Guard Page → SIGSEGV)
- TTSP (Time To Safepoint) — время от команды «стоп» до последнего остановленного потока; может быть дольше самого GC!
- Counted Loops — JIT не вставляет Safepoints в циклы
for (int i...)→ TTSP = секунды; решение:-XX:+UseCountedLoopSafepoints - Thread-Local Handshakes (Java 11+) — операция с конкретным потоком без остановки всех остальных
- JNI-потоки: JVM ждёт, пока JNI-поток вернётся в Java-код; поток НЕ работает во время STW, он заблокирован при попытке вернуться
- Polling page — чтение из кэша (страница почти всегда в L1) быстрее ветвления; почти нулевой overhead
Частые уточняющие вопросы:
- Почему TTSP может быть дольше самого GC? — Counted Loops без Safepoints, массивный I/O (поток в системном вызове), свопинг страницы Safepoint
- Как диагностировать длинные TTSP? —
-Xlog:safepoint(ищите “reaching safepoint” > 100 мс); JFR: событие Safepoint Begin → entering/waiting/cleanup - Что такое Thread-Local Handshakes? — Java 11+: handshake с конкретным потоком вместо остановки всех; примеры: Thread Dump, Biased Lock отзыв
- Почему Safepoint Polling быстрее флагового check? — Чтение из кэша L1 (страница почти всегда там) быстрее branch; fast path = почти 0 overhead
Красные флаги (НЕ говорить):
- «STW нужен только для GC» — STW также для thread dumps, biased lock revocation, class redefinition
- «JNI-потоки работают во время STW» — JNI-поток заблокирован при попытке вернуться в Java; JVM ждёт его
- «Counted Loops не влияют на производительность» — без Safepoints TTSP может быть секунды
Связанные темы:
- [[4. Что такое Garbage Collection]]
- [[17. Какие GC минимизируют stop-the-world паузы]]
- [[14. Что такое ZGC]]
- [[13. Что такое G1 GC]]
- [[12. Какие алгоритмы GC существуют]]