OutOfMemoryError: Перевищено ліміт накладних витрат GC

1. Огляд

Простіше кажучи, JVM піклується про звільнення пам’яті, коли об’єкти більше не використовуються; цей процес називається Збір сміття (GC).

Верхня межа Exceeded ОЙ помилка одна з сімейства java.lang.OutOfMemoryError і є показником ресурсу (пам'ять) виснаження.

У цій короткій статті ми розглянемо причини того, що спричиняє помилку java.lang.OutOfMemoryError: GC Overhead Limit Overeded, і як її можна вирішити.

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 dataMap = new HashMap(); Random r = new Random(); while (true) { dataMap.put(r.nextInt(), String.valueOf(r.nextInt())); } } }

При виклику цього методу з аргументами JVM як -Xmx100m -XX: + UseParallelGC ( розмір кучі Java встановлений на 100 Мб, а алгоритм GC - паралельний GC), ми отримуємо помилку java.lang.OutOfMemoryError: GC Overhead Limit Exceeded . Щоб краще зрозуміти різні алгоритми збору сміття, ми можемо ознайомитися з підручником Основи збору сміття Java Oracle.

Ми отримаємо java.lang.OutOfMemoryError: Помилка перевищення накладних витрат GC дуже швидко, виконавши наступну команду з кореня проекту:

mvn exec:exec

Слід також зазначити , що в деяких ситуаціях ми можемо зіткнутися з купою помилок простору до зустрічі з Exceeded GC Накладні Обмежити помилку.

4. Вирішення перевищення ліміту накладних витрат GC

Ідеальне рішення - знайти основну проблему програми, вивчивши код на предмет витоків пам'яті.

Потрібно розглянути такі питання:

  • Які об’єкти в програмі займають великі частини купи?
  • У яких частинах вихідного коду виділяються ці об’єкти?

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

Останнім засобом було б збільшити розмір купи, змінивши конфігурацію запуску JVM. Наприклад, це дає 1 ГБ простору для Java-програми:

java -Xmx1024m com.xyz.TheClassName

Однак це не вирішить проблему, якщо фактичний код програми має витоки пам'яті. Натомість ми просто відкладемо помилку. Тому доцільніше ретельно оцінити використання пам'яті програми.

5. Висновок

У цьому навчальному посібнику ми розглянули java.lang.OutOfMemoryError: Перевищено ліміт накладних витрат GC та причини цього.

Як завжди, вихідний код, пов'язаний з цією статтею, можна знайти на GitHub.