1 статья, чтобы понять причины и решения 8 видов JVM нехватки памяти (OOM)

Java

предисловие

Изучающие Java в большей или меньшей степени будут сталкиваться со сценариями переполнения памяти (OOM), но причины OOM могут быть различными.

переполнение кучи

Этот сценарий является наиболее распространенным, и сообщение об ошибке:
java.lang.OutOfMemoryError: Java heap space

причина

1. В коде могут быть большие выделения объектов 2. Могут быть утечки памяти, из-за которых невозможно найти кусок памяти, достаточно большой для размещения текущего объекта после нескольких GC.

Решение

1. Проверяем, есть ли выделение больших объектов, скорее всего выделения больших массивов
2. С помощью команды jmap сделайте дамп памяти кучи, используйте инструмент mat для ее анализа и проверьте, нет ли проблемы с утечкой памяти.
3. Если очевидных утечек памяти не обнаружено, используйте -Xmx для увеличения памяти кучи.
4. Еще один момент, который легко упускается из виду — проверить, есть ли большое количество пользовательских объектов Finalizable, которые также могут быть предоставлены фреймворком, и рассмотреть необходимость их существования.

Постоянная генерация/переполнение метапространства

Сообщение об ошибке:
java.lang.OutOfMemoryError: PermGen spacejava.lang.OutOfMemoryError: Metaspace

причина

Постоянное поколение — это конкретная реализация области методов виртуальной машиной HotSot, которая хранит информацию о классе, константы, статические переменные и JIT-компилированный код, загружаемый виртуальной машиной.
После JDK8 метапространство заменило постоянное поколение, метапространство использовало локальную память, и другие детали изменились:
  • Строковые константы переносятся из постоянной генерации в кучу
  • Параметры JVM, связанные с постоянной генерацией, были удалены.
Возможные причины следующие:
1. До появления Java7 метод String.intern() часто использовался некорректно 2. Во время работы генерировалось большое количество прокси-классов, из-за чего область метода взрывалась и не могла быть удалена 3. Приложение работало некоторое время долгое время без перезагрузки.
Как правило, во время отладки не удается перезапустить процесс JVM, как показано в разделе часто задаваемых вопросов на официальном веб-сайте Tomcat ниже:
Почему использование памяти увеличивается при повторном развертывании веб-приложения? Это связано с тем, что в вашем веб-приложении есть утечка памяти. Распространенной проблемой являются утечки памяти «PermGen». Они происходят из-за того, что загрузчик классов (и загруженные им объекты классов) не могут быть переработаны если не выполняются некоторые требования (). Они хранятся в постоянной куче генерации JVM, и при повторном развертывании создается новый загрузчик классов, который загружает другую копию всех этих классов. В конечном итоге это может вызвать OufOfMemoryErrors. (*) Требование состоит в том, чтобы все классы, загруженные этим загрузчиком классов, могли быть собраны одновременно.

Решение

Поскольку причина OOM относительно проста, решения следующие:
1. Проверьте, не установлено ли слишком маленькое пространство постоянного поколения или метапространство.
2. Проверьте, много ли в коде операций отражения
3. После дампа проверить, нет ли большого количества прокси-классов, сгенерированных отражением через мат
4. Увеличьте масштаб и перезапустите JVM.

GC overhead limit exceeded

Это исключение встречается относительно редко, и сообщение об ошибке:
java.lang.OutOfMemoryError:GC overhead limit exceeded

причина

Это новый тип ошибки, добавленный в JDK6, который обычно возникает из-за того, что куча слишком мала. Официальное определение Sun: это исключение выдается, когда более 98 % времени используется для GC и восстанавливается менее 2 % памяти кучи.

Решение

1. Проверьте, нет ли в проекте большого количества бесконечных циклов или кода, использующего большой объем памяти, и оптимизируйте код.
2. Добавьте параметр -XX:-UseGCOverheadLimit для отключения этой проверки.На самом деле этот параметр не может решить проблему с памятью.Он просто задерживает неверную информацию,и в итоге появляется java.lang.OutOfMemoryError: Java heap space.
3. Сделать дамп памяти, чтобы проверить, есть ли утечка памяти, если нет, увеличить память.

переполнение стека методов

Сообщение об ошибке:
java.lang.OutOfMemoryError : unable to create new native Thread

причина

Такое исключение в основном вызвано созданием большого количества потоков, я уже сталкивался с этим однажды, и всего через jstack вышло более 8000 потоков.

Решение

1. Емкость размера стека каждого потока уменьшена на -Xss 2. Общее количество потоков также ограничено свободной памятью системы и операционной системой.Проверьте, есть ли в системе это ограничение:
  • /proc/sys/kernel/pid_max
  • /proc/sys/kernel/thread-max
  • maxuserprocess (ulimit -u)
  • /proc/sys/vm/maxmapcount

нетрадиционный перелив

Следующие исключения OOM могут не встречаться большинству учащихся, но их все же необходимо понять.
Выделить очень большой массив
Сообщение об ошибке:
java.lang.OutOfMemoryError: Requested array size exceeds VM limit
Эта ситуация обычно вызвана необоснованным запросом на выделение массива, и JVM выполняет проверку перед выделением памяти для массива. Является ли выделяемый массив адресуемым на этой платформе (адресуемым), если он не адресуемым (адресуемым), будет выдана эта ошибка.
Решение состоит в том, чтобы проверить свой код на наличие мест, где создаются очень большие массивы.

переполнение подкачки

Сообщение об ошибке:
java.lang.OutOfMemoryError: Out of swap space
Эта ситуация обычно вызвана операционной системой, и возможные причины:
1. Недостаточное выделение размера раздела подкачки;
2. Другие процессы потребляют всю память.
решение:
1. Другие служебные процессы могут быть выборочно разделены 2. Увеличьте размер раздела подкачки или увеличьте размер машинной памяти

переполнение собственного метода

Сообщение об ошибке:
java.lang.OutOfMemoryError: stack_trace_with_native_method
Собственный метод имеет сбой выделения памяти во время выполнения.В отличие от предыдущего переполнения стека метода, переполнение стека метода происходит на уровне кода JVM, а переполнение собственного метода происходит на уровне кода JNI или собственного метода.
Вероятность возникновения этой аномалии крайне мала, и диагностировать ее можно только через локальные средства операционной системы, что немного сложно, поэтому лучше сдаться.

Наконец

Прошу всех обратить внимание на мой Gongzhonghao [Программист в погоне за ветром], в нем будут обновляться статьи, а также размещаться отсортированная информация.