Я знаю, что такое OutOfMemoryError, но что означает ограничение накладных расходов GC? Как я могу это решить?
Переведено автоматически
Ответ 1
Это сообщение означает, что по какой-то причине сборщик мусора отнимает чрезмерное количество времени (по умолчанию 98% всего процессорного времени процесса) и восстанавливает очень мало памяти при каждом запуске (по умолчанию 2% кучи).
Фактически это означает, что ваша программа перестает выполнять какой-либо прогресс и все время занята только сборкой мусора.
Чтобы ваше приложение не тратило процессорное время без выполнения каких-либо действий, JVM выдает это Error чтобы у вас был шанс диагностировать проблему.
Редкие случаи, когда я видел, как это происходило, заключались в том, что какой-то код создавал тонны временных объектов и тонны объектов со слабыми ссылками в среде, и без того сильно ограниченной памятью.
Ознакомьтесь с руководством по настройке Java GC, которое доступно для различных версий Java и содержит разделы, посвященные этой конкретной проблеме:
Параллельный сборщик выдаст OutOfMemoryError, если на сборку мусора тратится слишком много времени: если на сборку мусора потрачено более 98% общего времени и восстановлено менее 2% кучи, будет выдан OutOfMemoryError. Эта функция предназначена для предотвращения запуска приложений в течение длительного периода времени при незначительном прогрессе или вообще без него, поскольку куча слишком мала. При необходимости эту функцию можно отключить, добавив опцию -XX:-UseGCOverheadLimit в командную строку.
РЕДАКТИРОВАТЬ: похоже, кто-то может печатать быстрее меня :)
Ответ 3
Если вы уверены, что в вашей программе нет утечек памяти, попробуйте:
Увеличьте размер кучи, например -Xmx1g.
Включите сборщик с одновременной низкой паузой -XX:+UseConcMarkSweepGC.
По возможности повторно используйте существующие объекты для экономии памяти.
При необходимости проверку лимита можно отключить, добавив опцию -XX:-UseGCOverheadLimit в командную строку.
Ответ 4
Обычно это код. Вот простой пример:
import java.util.*;
publicclassGarbageCollector {
publicstaticvoidmain(String... args) {
System.out.printf("Testing...%n"); List<Double> list = newArrayList<Double>(); for (intouter=0; outer < 10000; outer++) {
// list = new ArrayList<Double>(10000); // BAD // list = new ArrayList<Double>(); // WORSE list.clear(); // BETTER
for (intinner=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 в 32-разрядной версии Windows 7.
java -Xloggc:gc.log GarbageCollector
Затем посмотрите на gc.log
Срабатывало 444 раза с использованием НЕПРАВИЛЬНОГО метода
Срабатывало 666 раз с использованием ХУДШЕГО метода
Срабатывало 354 раза с использованием ЛУЧШЕГО метода
Теперь понятно, что это не лучший тест или не лучший дизайн, но когда вы сталкиваетесь с ситуацией, когда у вас нет выбора, кроме реализации такого цикла, или когда вы имеете дело с существующим кодом, который ведет себя плохо, выбор повторного использования объектов вместо создания новых может уменьшить количество раз, когда сборщик мусора мешает...