Що таке параметри -Xms та -Xmx?
→ Без пауз на розширення пам'яті
🟢 Junior Level
-Xms та -Xmx — параметри для налаштування розміру Heap пам’яті Java.
-Xms — початковий розмір Heap (скільки пам’яті взяти при старті) -Xmx — максимальний розмір Heap (більше цього не брати)
Приклад:
java -Xms512m -Xmx2g MyApp
# Старт: 512 МБ
# Максимум: 2 ГБ
У більшості production-сценаріїв: -Xms = -Xmx (запобігає overhead на resizing). Винятки: CLI-утиліти (маленький -Xms для швидкого старту), memory-constrained середовища.
→ Без пауз на розширення пам’яті
🟡 Middle Level
Reserved vs Committed
-Xmx4g:
→ JVM резервує 4 ГБ віртуальної пам'яті
→ Фізична пам'ять виділяється в міру необхідності
-Xms4g:
→ Одразу виділяються 4 ГБ фізичної пам'яті
Чому -Xms = -Xmx
Якщо -Xms < -Xmx:
1. Додаток росте → потрібен більший Heap
2. JVM намагається уникнути розширення: спочатку запускає GC, щоб звільнити місце в поточному Heap.
У сучасних GC (G1) це зазвичай Young/Mixed GC, а не Full GC.
Але якщо GC не допоміг — JVM запитує більше пам'яті у ОС.
3. Пауза!
4. Розширення → системний виклик
Якщо -Xms = -Xmx:
→ Немає пауз на ресайз
→ Стабільні пороги GC
→ Передбачувана поведінка
Docker/Kubernetes
# Сучасний підхід (Java 11+):
-XX:InitialRAMPercentage=75.0
-XX:MaxRAMPercentage=75.0
# JVM читає ліміт контейнера
# → 75% від RAM контейнера = Heap
# → Гнучко: змінюєте ліміт у YAML → Heap змінюється
AlwaysPreTouch
-XX:+AlwaysPreTouch
# При старті: фізично виділити всі сторінки
# → Старт довший
# → Немає мікро-затримок при першому зверненні
# → Гарантовано, що пам'ять виділена
🔴 Senior Level
Transparent Huge Pages (THP)
Linux: Huge Pages = 2 МБ замість 4 КБ
→ Менше TLB misses
→ +5-10% продуктивності
Проблема: THP конфліктує з G1
→ Довгі паузи GC
Рішення:
1. Вимкнути THP на рівні ядра
2. Використати статичні Huge Pages:
-XX:+UseLargePages
Native Memory = не тільки Heap
RSS (загальна пам'ять процесу) =
Heap (-Xmx)
+ Metaspace
+ Code Cache
+ Thread Stacks (-Xss × потоки)
+ Direct Buffers
+ GC Overhead
→ -Xmx30g на 32 ГБ сервері = OOM Killer!
→ Залишайте 20-30% на Native Memory
NMT (Native Memory Tracking)
-XX:NativeMemoryTracking=summary
jcmd <pid> VM.native_memory summary
# Покаже:
# Java Heap: 30 GB
# Class: 50 MB
# Thread: 100 MB
# Code: 80 MB
# GC: 200 MB
# Internal: 50 MB
# ...
Best Practices
- -Xms = -Xmx у production
- RAMPercentage для контейнерів
- AlwaysPreTouch для стабільності
- Залишайте 20-30% на Native Memory
- NMT для моніторингу
- Уникайте THP з G1
- Не ставте -Xmx впритул до RAM
Резюме для Senior
- -Xms = -Xmx = без пауз на ресайз
- RAMPercentage = гнучкість у контейнерах
- AlwaysPreTouch = немає page fault затримок
- RSS > -Xmx = Native Memory враховуйте
- NMT = моніторинг всієї пам’яті
- THP = обережно з G1
- OOM Killer = якщо -Xmx занадто близький до RAM
🎯 Шпаргалка для інтерв’ю
Обов’язково знати:
-Xms— початковий розмір Heap,-Xmx— максимальний; у production-Xms = -Xmxдля запобігання паузам на ресайз- Reserved vs Committed:
-Xmxрезервує віртуальну пам’ять;-Xmsодразу виділяє фізичну - При розширенні Heap (
-Xms < -Xmx): JVM спочатку запускає GC → якщо не допоміг → системний виклик до ОС → пауза - Docker/Kubernetes:
-XX:InitialRAMPercentage=75.0/-XX:MaxRAMPercentage=75.0— JVM читає ліміт контейнера - AlwaysPreTouch: при старті фізично виділити всі сторінки → старт довший, але немає мікро-затримок при першому зверненні
- RSS = Heap + Metaspace + Code Cache + Thread Stacks + Direct Buffers + GC Overhead; залишайте 20-30% RAM на Native Memory
- Transparent Huge Pages (THP): +5-10% продуктивності, але конфліктує з G1 → довгі паузи
Часті уточнюючі запитання:
- Чому
-Xms = -Xmxу production? — Без пауз на розширення Heap; стабільні пороги GC; передбачувана поведінка - Що буде, якщо поставити
-Xmx30gна 32 ГБ сервері? — OOM Killer вб’є процес: RSS > 32 ГБ (Metaspace + Stacks + Code Cache ще 2-4 ГБ) - Навіщо AlwaysPreTouch? — Запобігає page fault затримкам при першому зверненні до сторінок; гарантує, що пам’ять реально виділена
- Чому THP конфліктує з G1? — G1 використовує регіони різного розміру; THP (2 МБ сторінки) викликає фрагментацію → довгі паузи GC
Червоні прапорці (НЕ говорити):
- «
-Xmx— це вся пам’ять процесу» — RSS значно більша: Metaspace, Stacks, Code Cache, Direct Buffers - «THP завжди покращує продуктивність» — конфліктує з G1; вимикайте або використовуйте статичні Huge Pages
- «У контейнері JVM автоматично використовує весь ліміт» — без RAMPercentage JVM бачить хост, а не контейнер (Java 8 без патчів)
Пов’язані теми:
- [[1. В чому різниця між Heap та Stack]]
- [[2. Що зберігається в Heap]]
- [[19. Що станеться при OutOfMemoryError]]
- [[22. Які інструменти допомагають аналізувати пам’ять]]
- [[11. Що таке Metaspace (або PermGen)]]