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.