Ответ
OutOfMemoryError (OOM) — критическая ошибка, возникающая, когда JVM не может выделить память для нового объекта, и сборщик мусора (GC) не может освободить достаточное количество памяти.
Процесс аллокации и эскалации до OOM:
- Запрос на аллокацию: JVM пытается выделить память в куче (heap) для создания нового объекта.
- Нехватка памяти: Если в текущем поколении (Eden Space) недостаточно свободного непрерывного пространства, запускается малая сборка мусора (Minor GC).
- Эскалация: Если после Minor GC памяти всё ещё не хватает, JVM пытается выделить объект непосредственно в старом поколении (Old Generation). При неудаче запускается полная сборка мусора (Full GC).
- Расшение кучи: Если после Full GC памяти недостаточно, JVM пытается расширить размер кучи в пределах, заданных параметром
-Xmx(максимальный размер). - Исключение: Если расширение невозможно (достигнут
-Xmx) или не помогает, JVM выбрасываетOutOfMemoryError.
Пример, вызывающий OOM в куче:
// Запуск: java -Xmx10m -Xms10m OOMDemo
import java.util.ArrayList;
import java.util.List;
public class OOMDemo {
public static void main(String[] args) {
List<Object> leak = new ArrayList<>();
while (true) {
leak.add(new byte[1024 * 1024]); // Аллокация по 1 МБ
}
}
}
Основные типы OutOfMemoryError:
Java heap space— классическая нехватка памяти в куче для объектов.Metaspace— исчерпана память для метаданных классов (заменяет PermGen).Direct buffer memory— переполнена память, выделенная для NIOByteBuffer.allocateDirect().Unable to create new native thread— превышен лимит на количество потоков ОС.Requested array size exceeds VM limit— попытка создать массив размером большеInteger.MAX_VALUE - 2или доступной памяти.
Best Practice: Для диагностики используйте профилировщики (VisualVM, JProfiler) и анализируйте дампы кучи, создаваемые с помощью параметров -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/to/dump.hprof.