Настройте Java GC, чтобы он сразу выбрасывал OOME, а не замедлялся до бесконечности - PullRequest
5 голосов
/ 15 июля 2011

Я заметил, что иногда, когда память почти исчерпана, сборщик мусора пытается завершить работу любой ценой производительности (вызывает почти зависание программы, иногда несколько минут ), а не просто бросить OOME (OutOfMemoryError) немедленно.

Есть ли способ настроить GC относительно этого аспекта?

Замедление программы до почти нулевой скорости делает ее не отвечающей . В некоторых случаях было бы лучше иметь ответ «Я мертв» , а не вообще никакого ответа.

Ответы [ 4 ]

8 голосов
/ 15 июля 2011

Нечто похожее на то, что вам нужно, встроено в последние JVM.

Если вы:

  • используете виртуальную машину Hotspot из (как минимум) Java 6
  • используют параллельные или параллельные сборщики мусора
  • имеют включенную опцию UseGCOverheadLimit (она включена по умолчанию для этих сборщиков, поэтому, в частности, если вы не отключили it)

тогда вы получите OOM до того, как на самом деле не хватит памяти: если более 98% недавнего времени было потрачено в GC на восстановление <2% размера кучи, вы получите упреждающийOOM. </p>

Настройка этих параметров (в частности, 98%) звучит так, как будто это было бы полезно для вас, однако, насколько я знаю, я не могу настроить эти пороги.

Однако убедитесь, что вы подходите под три пункта выше;если вы не используете эти коллекторы с этим флагом, это может помочь в вашей ситуации.

Стоит прочитать руководство по настройке HotSpot JVM , которое может очень помочь в этом.

2 голосов
/ 15 июля 2011

Я не знаю ни одного способа настройки сборщика мусора Java описанным вами способом.

Одним из способов может быть то, что ваше приложение может предварительно контролировать объем свободной памяти, например, используя Runtime.freeMemory() и объявите условие «Я мертв» , если оно опускается ниже определенного порога и не может быть исправлено с помощью цикла принудительного сбора мусора.

Идеяэто выбрать значение для порога, которое достаточно велико для того, чтобы процесс никогда не попадал в описанную вами ситуацию.

1 голос
/ 15 июля 2011

Я настоятельно рекомендую против этого: Java, пытающаяся GC вместо того, чтобы немедленно генерировать исключение OutOfMemoryException, имеет гораздо больший смысл - не заставляйте ваше приложение отказываться, пока не исчерпаны все альтернативы.

Если вашему приложению не хватает памяти, вы должны увеличить максимальный размер кучи или посмотреть на его производительность с точки зрения выделения памяти и посмотреть, можно ли его оптимизировать.

Вот некоторые вещи, на которые стоит обратить внимание:

  • Используйте слабые ссылки в тех местах, где ваши объекты не понадобятся, если на них нет ссылок нигде.
  • Не выделяйте объекты большего размера, чем вам нужно (т. Е. Храните огромный массив из 100 объектов, когда вам нужен только доступ к трем из них в течение жизненного цикла массива), и не используйте длинный тип данных, когда вам нужно только сохранить восемь значений.
  • Не держите ссылки на объекты дольше, чем нужно!

Редактировать: Я думаю, вы неправильно поняли мою точку зрения. Если вы случайно оставите живую ссылку на объект, который больше не нужно использовать, он, очевидно, все равно не будет собирать мусор. Это не имеет ничего общего с обнулением, просто incase - типичным примером этого является использование большого объекта для определенной цели, но когда он выходит из области видимости, это не GC, потому что живая ссылка случайно была оставлена ​​в другом месте, где-то, что вы не знаю о причинении утечки. Типичным примером этого может служить поиск в хеш-таблице, который может быть решен с помощью слабых ссылок, так как он будет иметь право на сборщик мусора, когда он только слабо доступен.

Несмотря на это, это просто общие идеи о том, как улучшить производительность с выделением памяти. Суть, которую я пытаюсь сделать, заключается в том, что вопрос о том, как быстрее вызвать ошибку OutOfMemory, а не о том, чтобы Java GC попытался найти лучший способ освободить место в куче, не является хорошей идеей для IMO. Вместо этого оптимизируйте свое приложение.

0 голосов
/ 09 июля 2018

Ну, получается, есть решение, так как Java8 b92 :

-XX:+ExitOnOutOfMemoryError
Когда вы включаете эту опцию, JVM завершает работу при первом появлении ошибки нехватки памяти. Его можно использовать, если вы предпочитаете перезапускать экземпляр JVM, а не обрабатывать ошибки нехватки памяти.

-XX:+CrashOnOutOfMemoryError
Если этот параметр включен, при возникновении ошибки нехватки памяти JVM аварийно завершает работу и создает текстовые и двоичные файлы сбоев (если включены основные файлы).

Хорошая идея - объединить один из вышеперечисленных вариантов со старым добрым -XX:+HeapDumpOnOutOfMemoryError

Я протестировал эти опции, они на самом деле работают, как и ожидалось!

Ссылки

См. Описание функции

См. Список изменений в этой версии Java

...