Какие типы OutOfMemoryError существуют?
4. MaxDirectMemorySize — контроль NIO 5. Мониторьте dmesg для OOM Killer 6. jcmd VM.metaspace для анализа Metaspace
🟢 Junior Level
OutOfMemoryError бывает разных типов — каждый указывает на свою проблему:
| Тип | Что значит |
|---|---|
| Java heap space | Heap переполнен |
| GC overhead limit exceeded | GC работает постоянно |
| Metaspace | Метаданные классов переполнены |
| Direct buffer memory | Память вне Heap (NIO) |
| Unable to create new native thread | Лимит потоков ОС |
🟡 Middle Level
Java heap space
Причина: утечка или маленький -Xmx
Решение:
1. -XX:+HeapDumpOnOutOfMemoryError
2. Анализ в MAT
3. Найти утечку или увеличить -Xmx
GC overhead limit exceeded
98% времени на GC, < 2% освобождается
→ Приложение "зависло" в бесконечном цикле Full GC
Решение:
- Увеличить Heap
- Найти утечку
- Отключить: -XX:-UseGCOverheadLimit (не рекомендуется!)
Metaspace
Метаданные классов переполнены
Причины:
- Динамическая генерация (Spring, CGLIB)
- Утечка ClassLoader-ов
Решение:
-XX:MaxMetaspaceSize=512m
jcmd <pid> VM.metaspace
Direct buffer memory
NIO память вне Heap
Причины: Netty, ByteBuffer.allocateDirect()
Решение:
-XX:MaxDirectMemorySize=2g
Проверить утечки в Netty
Unable to create new native thread
ОС не может создать поток
Причины:
- ulimit -u достигнут
- RAM для стеков (-Xss) закончилась
Решение:
Уменьшить -Xmx (больше RAM для стеков)
Проверить ulimit -u
🔴 Senior Level
Requested array size exceeds VM limit
Массив > Integer.MAX_VALUE элементов
→ Чаще всего указывает на ошибку в логике. Но бывают легитимные случаи: попытка загрузить большой файл в память целиком.
Compressed Class Space
Compressed Class Space — часть Metaspace для сжатых указателей на классы (4 байта вместо 8).
Лимит: -XX:CompressedClassSpaceSize (1 ГБ по умолчанию). Переполнение → OOME, даже если Metaspace свободен.
Map failed (Memory Mapped Files)
MappedByteBuffer.map() → ошибка
→ vm.max_map_count достигнут
→ Нет виртуальной памяти для маппинга
Решение: sysctl -w vm.max_map_count=262144
Linux OOM Killer
НЕ Java ошибка!
→ Контейнер: лимит < RSS
→ ОС убивает процесс через SIGKILL
→ Нет дампов, нет логов!
Диагностика:
dmesg | grep -i oom
→ "Out of memory: Kill process"
Сводная таблица
| Тип | Куда смотреть | Флаг |
|---|---|---|
| Heap | Утечки в Heap | HeapDumpOnOOM |
| Metaspace | ClassLoader leaks | VM.metaspace |
| Direct buffer | Netty/NIO | NMT |
| Native thread | ulimit, -Xss | ps -Hu |
| GC overhead | Thrashing | GC Logs |
Best Practices
- HeapDumpOnOutOfMemoryError — обязательно
- NMT=detail для Native Memory
- MaxMetaspaceSize — лимит для контейнеров
- MaxDirectMemorySize — контроль NIO
- Мониторьте dmesg для OOM Killer
- jcmd VM.metaspace для анализа Metaspace
Резюме для Senior
- Тип OOME = первая улика в расследовании
- Heap space = утечки в Heap
- Metaspace = ClassLoader leaks
- Direct buffer = NIO утечки (вне Heap)
- Native thread = лимиты ОС
- OOM Killer = не Java ошибка (контейнеры)
- NMT = диагностика Native Memory
🎯 Шпаргалка для интервью
Обязательно знать:
Java heap space— Heap переполнен; решение: HeapDumpOnOOM + MAT анализ + найти утечку или увеличить -XmxGC overhead limit exceeded— 98% времени на GC, < 2% освобождается; бесконечный цикл Full GCMetaspace— метаданные классов переполнены; причины: динамическая генерация (Spring, CGLIB), утечка ClassLoaderDirect buffer memory— NIO память вне Heap; Netty, ByteBuffer.allocateDirect(); решение: MaxDirectMemorySizeUnable to create new native thread— ulimit -u достигнут или RAM для стеков (-Xss) закончиласьRequested array size exceeds VM limit— массив > Integer.MAX_VALUE; чаще ошибка в логике- Linux OOM Killer — НЕ Java ошибка! Контейнер: лимит < RSS → ОС убивает через SIGKILL → нет дампов
Частые уточняющие вопросы:
- Как отличить JVM OOME от OS OOM Killer? — JVM OOME: стек-трейс в логах; OOM Killer:
dmesg | grep -i oom, процесс исчезает без логов - Что такое Compressed Class Space OOME? — Часть Metaspace для сжатых указателей на классы (1 ГБ лимит); переполнение → OOME, даже если Metaspace свободен
- Почему «Requested array size exceeds VM limit» случается? — Попытка создать массив > Integer.MAX_VALUE элементов; часто баг (загрузка большого файла целиком)
- Как диагностировать OOM Killer в Kubernetes? —
dmesg | grep -i oom; Pod terminated (OOMKilled); решение: увеличить лимит или уменьшить RSS
Красные флаги (НЕ говорить):
- «Отключу
-XX:-UseGCOverheadLimitи проблема решится» — это маскирует проблему; приложение всё равно упадёт с Heap space OOME - «OOM Killer — это баг Java» — это решение ОС; Java не контролирует лимиты контейнера
- «Direct buffer memory = часть Heap» — DirectByteBuffer выделяет память ВНЕ Heap (
-Xmxне влияет)
Связанные темы:
- [[19. Что произойдёт при OutOfMemoryError]]
- [[11. Что такое Metaspace (или PermGen)]]
- [[6. Что такое утечка памяти в Java]]
- [[18. Что такое параметры -Xms и -Xmx]]
- [[21. Что такое memory leak и как его обнаружить]]