Вопрос 16 · Раздел 3

Что такое stop-the-world?

JVM использует polling page (страницу памяти) вместо флагового check, потому что чтение из кэша (страница почти всегда в L1) быстрее, чем ветвление (branch). Это «fast path» — п...

Версии по языкам: English Russian Ukrainian

🟢 Junior Level

Stop-The-World (STW) — это когда JVM останавливает все потоки приложения для выполнения GC.

Простая аналогия: Представьте, что вы работаете в офисе, и вдруг объявляют эвакуацию. Все останавливаются и ждут, пока проверка закончится.

Зачем нужен STW:

  1. GC — нужно консистентное состояние памяти (объекты не перемещаются во время обхода)
  2. Не-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

  1. Мониторьте TTSP через safepoint логи
  2. Counted Loops → UseCountedLoopSafepoints
  3. Handshakes (Java 11+) → меньше STW
  4. JFR для визуализации
  5. Избегайте длинных циклов без Safepoints
  6. 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 существуют]]