Питання 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) швидше branch; fast path = майже 0 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 існують]]