Ответ
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.
Ответ 18+ 🔞
А, блядь, OutOfMemoryError! Ну это ж классика, ёпта, как борщ со сметаной. Это когда твоя Java-машина (JVM), такая, понимаешь, мартышлюшка, уже не может нигде найти местечка для новой переменной, и даже сборщик мусора, этот последний уборщик, размахивающий метлой, нихуя не может подмести.
Как всё это красиво разваливается, шаг за шагом:
- Хочу объект! Программа орёт: «Дай мне памяти для новой штуки!». JVM лезет в основную кучу (heap), как в карман.
- Места нет, сука. А в кармане, в молодом поколении (Eden Space), уже битком. JVM говорит: «Ладно, щас быстренько приберусь» — и запускает малую уборку (Minor GC). Выкидывает мусор, сдвигает что осталось.
- Всё равно не лезет. Если после этой суеты места всё равно нет, она пытается сунуть объект прямиком в старое поколение (Old Generation), типа в кладовку. Не получается? Ну всё, пиздец, объявляется генеральная уборка (Full GC). Весь дом перетряхивается.
- Расширяем владения. После генералки всё ещё тесно? JVM начинает раздвигать стены кучи, как живот у меня после пельменей, но только до предела, который ты ей задал (
-Xmx). - Финал. Если расширяться некуда или не помогло — BANG!
OutOfMemoryErrorпрямо в ебало. Всё, приехали.
Вот тебе наглядный пиздец, который это вызывает:
// Запускай так: 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 МБ, пока не лопнем
}
}
}
А ещё эта ошибка, блядь, бывает разная, как настроение у тещи:
Java heap space— самый родной, классический. Место в основной куче для объектов кончилось. Овердохуища всего наворотили.Metaspace— память для всяких служебных описаний классов (раньше PermGen была) забили. Классов насоздавали — хоть святых выноси.Direct buffer memory— это когда нажрались памяти мимо кучи, черезByteBuffer.allocateDirect(). Своего рода чёрный нал.Unable to create new native thread— операционка говорит: «Хуй тебе, а не ещё один поток!». Лимит исчерпан.Requested array size exceeds VM limit— ну это совсем уже, запросили массив размером с Луну. Даже JVM офигела.
Как не быть мудаком? Когда это случится (а случится), не охуевай просто так. Настрой дамп кучи на вылет: -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/куда/положить/dump.hprof. Потом этот дамп в профилировщик (типа VisualVM) — и смотри, кто там столько памяти жрёт, хитрая жопа.