Что такое параметры -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)]]