OutOfMemoryError: Превышен лимит накладных расходов GC

1. Обзор

Проще говоря, JVM заботится об освобождении памяти, когда объекты больше не используются; этот процесс называется сбором мусора (ссылка:/jvm-garbage-collectors[GC]).

Ошибка GC Overhead Limit Exceeded относится к семейству java.lang.OutOfMemoryError и указывает на исчерпание ресурса (памяти).

В этой быстрой статье мы рассмотрим причину ошибки java.lang.OutOfMemoryError: GC Overhead Limit Exceeded и ее решение.

2. Ошибка превышения предельного значения GC

OutOfMemoryError является подклассом java.lang.VirtualMachineError ; он генерируется JVM, когда сталкивается с проблемой, связанной с использованием ресурсов. В частности, ошибка возникает, когда JVM тратит слишком много времени на сборку мусора и может освободить только очень мало места в куче.

Согласно документации Java, по умолчанию JVM настроена на выдачу этой ошибки, если процесс Java тратит более 98% своего времени на выполнение GC, и когда при каждом запуске восстанавливается только менее 2% кучи. Другими словами, это означает, что наше приложение исчерпало почти всю доступную память, а сборщик мусора потратил слишком много времени, пытаясь его очистить, и неоднократно выходил из строя.

В этой ситуации пользователи испытывают крайнюю медлительность приложения.

Некоторые операции, которые обычно выполняются за миллисекунды, занимают больше времени. Это связано с тем, что процессор использует всю свою емкость для сборки мусора и, следовательно, не может выполнять какие-либо другие задачи.

3. Ошибка в действии

Давайте рассмотрим фрагмент кода, который генерирует __java.lang.OutOfMemoryError

Превышен предел накладных расходов GC.

Мы можем достичь этого, например, добавив пары ключ-значение в неопределенный цикл:

public class OutOfMemoryGCLimitExceed {
    public static void addRandomDataToMap() {
        Map<Integer, String> dataMap = new HashMap<>();
        Random r = new Random();
        while (true) {
            dataMap.put(r.nextInt(), String.valueOf(r.nextInt()));
        }
    }
}

Когда этот метод вызывается с аргументами JVM, такими как _- Xmx100m -XX: + UseParallelGC (размер кучи Java установлен на 100 МБ, а алгоритм GC равен ParallelGC), мы получаем ошибку java.lang.OutOfMemoryError: Ошибка превышения ограничения GC Exceeded_ . Чтобы лучше понять различные алгоритмы сбора мусора, мы можем обратиться к учебнику Oracle по Java Garbage Collection Basics учебнику.

Мы получим ошибку java.lang.OutOfMemoryError: GC Overhead Limit Exceeded очень быстро, выполнив следующую команду из корня project :

mvn exec:exec

Следует также отметить, что в некоторых ситуациях мы можем столкнуться с ошибкой пространства кучи, прежде чем встретим ошибку GC Overhead Limit Exceeded

4. Устранение ошибки превышения предельных значений ГХ

Идеальное решение - найти основную проблему с приложением, проверив код на наличие утечек памяти.

Необходимо ответить на следующие вопросы:

  • Какие объекты в приложении занимают большие порции

куча?

  • В каких частях исходного кода размещаются эти объекты?

Мы также можем использовать автоматизированные графические инструменты, такие как JConsole , которые помогают обнаруживать проблемы с производительностью в коде, включая java.lang. .OutOfMemoryErrors.

Последним средством будет увеличение размера кучи путем изменения конфигурации запуска JVM. Например, это дает 1 ГБ пространства кучи для приложения Java:

java -Xmx1024m com.xyz.TheClassName

Однако это не решит проблему, если в реальном коде приложения есть утечки памяти. Вместо этого мы просто отложим ошибку.

Поэтому более целесообразно пересмотреть использование памяти приложением.

5. Заключение

В этом руководстве мы рассмотрели __java.lang.OutOfMemoryError: Превышен предел накладных расходов GC и причины его возникновения

Как всегда, исходный код, связанный с этой статьей, можно найти на over на GitHub .