Ошибка java.lang.OutOfMemoryError: превышен лимит накладных расходов GC
Я получаю это сообщение об ошибке при выполнении моих тестов JUnit:
java.lang.OutOfMemoryError: GC overhead limit exceeded
Я знаю что OutOfMemoryError
есть, но что означает ограничение по накладным расходам GC? Как я могу решить это?
23 ответа
Это сообщение означает, что по какой-то причине сборщик мусора занимает слишком много времени (по умолчанию 98% всего процессорного времени процесса) и восстанавливает очень мало памяти при каждом запуске (по умолчанию 2% кучи).
Это фактически означает, что ваша программа перестает делать какой-либо прогресс и все время занята только сборкой мусора.
Чтобы приложение не впитывало процессорное время без каких-либо действий, JVM выдает это Error
так что у вас есть шанс диагностировать проблему.
Редкие случаи, когда я видел это, - это когда какой-то код создавал тонны временных объектов и тонны объектов со слабыми ссылками в среде с уже очень ограниченным объемом памяти.
Проверьте эту статью для деталей (особенно эта часть).
GC выдает это исключение, когда слишком много времени тратится на сборку мусора для слишком малого возврата, например. 98% процессорного времени тратится на сборку мусора, и восстанавливается менее 2% кучи.
Эта функция предназначена для предотвращения запуска приложений в течение длительного периода времени при небольшом прогрессе или его отсутствии, поскольку куча слишком мала.
Вы можете отключить это с параметром командной строки -XX:-UseGCOverheadLimit
Больше информации здесь
РЕДАКТИРОВАТЬ: похоже, кто-то может печатать быстрее, чем я:)
Если вы уверены, что в вашей программе нет утечек памяти, попробуйте:
- Увеличьте размер кучи, например
-Xmx1g
, - Включить параллельный коллектор с низкой паузой
-XX:+UseConcMarkSweepGC
, - Повторно используйте существующие объекты, когда это возможно, чтобы сэкономить память.
При необходимости проверку лимита можно отключить, добавив опцию -XX:-UseGCOverheadLimit
в командной строке.
Обычно это код. Вот простой пример:
import java.util.*;
public class GarbageCollector {
public static void main(String... args) {
System.out.printf("Testing...%n");
List<Double> list = new ArrayList<Double>();
for (int outer = 0; outer < 10000; outer++) {
// list = new ArrayList<Double>(10000); // BAD
// list = new ArrayList<Double>(); // WORSE
list.clear(); // BETTER
for (int inner = 0; inner < 10000; inner++) {
list.add(Math.random());
}
if (outer % 1000 == 0) {
System.out.printf("Outer loop at %d%n", outer);
}
}
System.out.printf("Done.%n");
}
}
Использование Java 1.6.0_24-b07 На Windows7 32 бит.
java -Xloggc: gc.log GarbageCollector
Тогда посмотрите на gc.log
- Сработало 444 раза, используя метод BAD
- Сработало 666 раз, используя метод WORSE
- Сработал 354 раза, используя метод ЛУЧШЕ
Конечно, это не лучший тест или лучший дизайн, но когда вы сталкиваетесь с ситуацией, когда у вас нет выбора, кроме как реализовать такой цикл или когда вы имеете дело с существующим кодом, который ведет себя плохо, выбор повторного использования объектов вместо создания новых может уменьшить сколько раз мешает сборщик мусора...
Причина ошибки
Превышен лимит накладных расходов GC "означает, что сборщик мусора работает все время, а Java-программа продвигается очень медленно.
После сборки мусора, если Java-процесс тратит более чем приблизительно 98% своего времени на сборку мусора, и если он восстанавливает менее 2% кучи и выполняет до сих пор последние 5 (постоянная времени компиляции) подряд коллекций, затем бросается java.lang.OutOfMemoryError
- Увеличьте размер кучи, если текущей кучи недостаточно.
- Если вы все еще получаете эту ошибку после увеличения памяти кучи, используйте инструменты профилирования памяти, такие как MAT (инструмент анализа памяти), Visual VM и т. Д., И исправьте утечки памяти.
- Обновите версию JDK до последней версии ( 1.8.x) или хотя бы 1.7.x и используйте алгоритм G1GC., Цель пропускной способности для G1 GC - 90% времени приложения и 10% времени сбора мусора
Помимо настройки памяти кучи с помощью -
Xms1g -Xmx2g
, пытаться-XX:+UseG1GC -XX:G1HeapRegionSize=n -XX:MaxGCPauseMillis=m -XX:ParallelGCThreads=n -XX:ConcGCThreads=n
Посмотрите на еще несколько связанных вопросов, касающихся G1GC
Java 7 (JDK 7) сборка мусора и документация по G1
Просто увеличьте размер кучи, установив эту опцию в
Выполнить → Запустить конфигурации → Аргументы → Аргументы виртуальной машины
-Xms1024M -Xmx2048M
Xms - для минимального лимита
Xmx - для максимального лимита
Попробуй это
Открой build.gradle
файл
android {
dexOptions {
javaMaxHeapSize = "4g"
}
}
Для меня сработали следующие шаги:
- Открой
eclipse.ini
файл + Изменить
-Xms40m -Xmx512m
в
-Xms512m -Xmx1024m
Перезапустите Eclipse
Следующее сработало для меня. Просто добавьте следующий фрагмент:
android {
compileSdkVersion 25
buildToolsVersion '25.0.1'
defaultConfig {
applicationId "yourpackage"
minSdkVersion 10
targetSdkVersion 25
versionCode 1
versionName "1.0"
multiDexEnabled true
}
dexOptions {
javaMaxHeapSize "4g"
}
}
Увеличьте javaMaxHeapsize в вашем файле build.gradle(модуль: приложение)
dexOptions {
javaMaxHeapSize "1g"
}
(добавить эту строку в Gradle)
dexOptions {
javaMaxHeapSize "4g"
}
Решено:
просто добавьте
org.gradle.jvmargs=-Xmx1024m
в
gradle.properties
а если его не существует, создайте его.
Вы также можете увеличить выделение памяти и размер кучи, добавив это в свой gradle.properties
файл:
org.gradle.jvmargs=-Xmx2048M -XX\:MaxHeapSize\=32g
Он не обязательно должен быть 2048M и 32g, сделайте его настолько большим, насколько хотите.
Описание размера кучи Java (xms, xmx, xmn)
-Xms size in bytes
Example : java -Xms32m
Устанавливает начальный размер кучи Java. Размер по умолчанию - 2097152 (2 МБ). Значения должны быть кратны 1024 байтам (1 КБ) и превышать их. (Флаг -server увеличивает размер по умолчанию до 32M.)
-Xmn size in bytes
Example : java -Xmx2m
Устанавливает начальный размер кучи Java для поколения Eden. Значение по умолчанию - 640 КБ. (Флаг -server увеличивает размер по умолчанию до 2M.)
-Xmx size in bytes
Example : java -Xmx2048m
Устанавливает максимальный размер, до которого может увеличиваться куча Java. Размер по умолчанию - 64 МБ. (Флаг -server увеличивает размер по умолчанию до 128 МБ.) Максимальный предел кучи составляет около 2 ГБ (2048 МБ).
Форматирование аргументов памяти Java (xms, xmx, xmn)
При установке размера кучи Java необходимо указать аргумент памяти, используя одну из букв "m" или "M" для МБ или "g" или "G" для ГБ. Ваша настройка не будет работать, если вы укажете "МБ" или "ГБ". Допустимые аргументы выглядят так:
-Xms64m или -Xms64M -Xmx1g или -Xmx1G Также можно использовать 2048 МБ для указания 2 ГБ Кроме того, убедитесь, что вы просто используете целые числа при указании аргументов. Использование -Xmx512m - допустимая опция, но -Xmx0.5g вызовет ошибку.
Эта ссылка может быть кому-то полезна.
Чтобы увеличить размер кучи в IntelliJ IDEA, выполните следующие инструкции. Это сработало для меня.
Для пользователей Windows,
Перейдите в место, где установлена IDE, и выполните поиск следующего.
idea64.exe.vmoptions
Отредактируйте файл и добавьте следующее.
-Xms512m
-Xmx2024m
-XX:MaxPermSize=700m
-XX:ReservedCodeCacheSize=480m
Вот и все!!
Я работаю в Android Studio и столкнулся с этой ошибкой при попытке создать подписанный APK для выпуска. Я смог создать и протестировать отладочный APK без проблем, но как только мне захотелось создать релизный APK, процесс сборки запускался бы несколько минут подряд, а затем, наконец, заканчивался сообщением об ошибке "java.lang.OutOfMemoryError: GC". превышен лимит накладных расходов ". Я увеличил размеры кучи для виртуальной машины и компилятора Android DEX, но проблема осталась. Наконец, после многих часов и кружек кофе выяснилось, что проблема была в моем файле на уровне приложения "build.gradle" - у меня был параметр "minifyEnabled" для типа сборки выпуска, установленный на "false", следовательно, запускались вещи Proguard в коде, который еще не прошел процесс сжатия кода (см. https://developer.android.com/studio/build/shrink-code.html). Я изменил параметр 'minifyEnabled' на 'true', и сборка релиза была выполнена как мечта:)
Короче говоря, мне пришлось изменить свой файл уровня приложения build.gradle с: //...
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.sign_config_release
}
debug {
debuggable true
signingConfig signingConfigs.sign_config_debug
}
}
//...
в
//...
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.sign_config_release
}
debug {
debuggable true
signingConfig signingConfigs.sign_config_debug
}
}
//...
Вы можете попробовать внести изменения в настройки сервера, обратившись к этому изображению и увеличив объем памяти для обработки изменений процесса, выделенных желтым цветом
вы также можете внести изменения в кучу java, открыв cmd-> set _java_opts -Xmx2g
2 г (2 гигабайта) в зависимости от сложности вашей программы
попробуйте использовать меньше постоянных переменных и временных переменных
Вам нужно увеличить размер памяти в Jdeveloper, перейти в setDomainEnv.cmd.
set WLS_HOME=%WL_HOME%\server
set XMS_SUN_64BIT=**256**
set XMS_SUN_32BIT=**256**
set XMX_SUN_64BIT=**3072**
set XMX_SUN_32BIT=**3072**
set XMS_JROCKIT_64BIT=**256**
set XMS_JROCKIT_32BIT=**256**
set XMX_JROCKIT_64BIT=**1024**
set XMX_JROCKIT_32BIT=**1024**
if "%JAVA_VENDOR%"=="Sun" (
set WLS_MEM_ARGS_64BIT=**-Xms256m -Xmx512m**
set WLS_MEM_ARGS_32BIT=**-Xms256m -Xmx512m**
) else (
set WLS_MEM_ARGS_64BIT=**-Xms512m -Xmx512m**
set WLS_MEM_ARGS_32BIT=**-Xms512m -Xmx512m**
)
а также
set MEM_PERM_SIZE_64BIT=-XX:PermSize=**256m**
set MEM_PERM_SIZE_32BIT=-XX:PermSize=**256m**
if "%JAVA_USE_64BIT%"=="true" (
set MEM_PERM_SIZE=%MEM_PERM_SIZE_64BIT%
) else (
set MEM_PERM_SIZE=%MEM_PERM_SIZE_32BIT%
)
set MEM_MAX_PERM_SIZE_64BIT=-XX:MaxPermSize=**1024m**
set MEM_MAX_PERM_SIZE_32BIT=-XX:MaxPermSize=**1024m**
Я получил эту ошибку при работе с сервером веб-логики Oracle. Я поделюсь своим ответом для справки на случай, если кто-то окажется здесь в поисках решения.
Итак, если вы пытаетесь запустить сервер веб-логики Oracle и получили эту ошибку, вам просто нужно увеличить начальный и максимальный размер кучи, установленный для запуска сервера.
Перейдите в -> C:\Oracle\Middleware\Oracle_Home\user_projects\domains\wl_server\bin
открыть setDomainEnv.cmd
проверьте значение USER_MEM_ARGS , если оно меньше
установить USER_MEM_ARGS = "- Xms128m - Xmx8192m $ {MEM_DEV_ARGS} $ {MEM_MAX_PERM_SIZE}"
Это означает, что ваш исходный размер кучи установлен на 128 МБ, а максимальный размер кучи составляет 8 ГБ. Теперь просто сохраните файл и перезапустите сервер. Если это не помогло решить проблему, попробуйте увеличить размер или поищите способы оптимизации службы.
для справки проверьте эту ссылку: https://docs.oracle.com/cd/E49933_01/server.770/es_install/src/tins_postinstall_jvm_heap.html
Если вы здесь ради исключения, которое поднимается в TOMCAT , то это для вас:
Это может случиться, если долго работать с этим котом.
Шаги:
- Перейдите в папку Tomcat (C:/tomcat).
- Там будет папка с именем «work», затем «catalina», затем «localHost».
- Удалить эту папку localhost
- Внутри C:/tomcat/webapps будут файлы, удалите все и пересоберите.
Теперь проблема с кучей памяти будет решена.
В Netbeans может быть полезно создать максимальный размер кучи. Перейдите в Run => Set Configuration Configuration => Customize. В появившемся окне Run, перейдите в VM Option, заполните -Xms2048m -Xmx2048m
, Это может решить проблему размера кучи.
@Buhb Я воспроизвел это в обычном веб-приложении с весенней загрузкой в его основном методе. Вот код:
public static void main(String[] args) {
SpringApplication.run(DemoServiceBApplication.class, args);
LOGGER.info("hello.");
int len = 0, oldlen=0;
Object[] a = new Object[0];
try {
for (; ; ) {
++len;
Object[] temp = new Object[oldlen = len];
temp[0] = a;
a = temp;
}
} catch (Throwable e) {
LOGGER.info("error: {}", e.toString());
}
}
Пример кода, вызвавший ошибку, также взят из спецификаций языка Oracle java8.
Я не знаю, актуально это до сих пор или нет, но просто хочу поделиться тем, что сработало для меня.
Обновите версию kotlin до последней доступной. https://blog.jetbrains.com/kotlin/category/releases/
и дело сделано.