1. Обзор
Проще говоря, JVM заботится об освобождении памяти, когда объекты больше не используются. Этот процесс называется сборкой мусора ( 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% своего времени на сборку мусора и когда при каждом запуске восстанавливается менее 2% кучи. Другими словами, это означает, что наше приложение исчерпало почти всю доступную память, а сборщик мусора потратил слишком много времени на ее очистку и несколько раз терпел неудачу.
В этой ситуации пользователи испытывают крайнюю медлительность приложения. Некоторые операции, которые обычно выполняются за миллисекунды, занимают больше времени. Это связано с тем, что ЦП использует всю свою мощность для сборки мусора и, следовательно, не может выполнять какие-либо другие задачи.
3. Ошибка в действии
Давайте посмотрим на фрагмент кода, который выдает ошибку java.lang.OutOfMemoryError: GC Overhead Limit Exceeded
.
Мы можем добиться этого, например, добавив пары ключ-значение в незавершенный цикл:
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 Overhead Limit Exceeded .
Чтобы лучше понять различные алгоритмы сборки мусора, ознакомьтесь с учебным пособием Oracle по основам сборки мусора Java .
Мы очень быстро получим ошибку java.lang.OutOfMemoryError: GC Overhead Limit Exceeded
, выполнив следующую команду из корня проекта :
mvn exec:exec
Следует также отметить, что в некоторых ситуациях мы можем столкнуться с ошибкой пространства в куче до появления ошибки GC Overhead Limit Exceeded
.
4. Устранение ошибки превышения лимита служебных данных GC
Идеальное решение — найти основную проблему с приложением, изучив код на наличие утечек памяти.
Эти вопросы необходимо решить:
- Какие объекты в приложении занимают большую часть кучи?
- В каких частях исходного кода размещаются эти объекты?
Мы также можем использовать автоматизированные графические инструменты, такие как JConsole , которые помогают обнаруживать проблемы с производительностью в коде, включая java.lang.OutOfMemoryErrors
.
В крайнем случае можно увеличить размер кучи, изменив конфигурацию запуска JVM.
Например, это дает 1 ГБ пространства кучи для приложения Java:
java -Xmx1024m com.xyz.TheClassName
Однако это не решит проблему, если в реальном коде приложения есть утечки памяти. Вместо этого мы просто отложим ошибку. Таким образом, более целесообразно тщательно переоценить использование памяти приложением.
5. Вывод
В этой статье мы рассмотрели ошибку java.lang.OutOfMemoryError: GC Overhead Limit Exceeded
и ее причины.
Как всегда, исходный код, относящийся к этой статье, можно найти на GitHub .