Продолжительность чрезмерного времени GC в «java.lang.OutOfMemoryError: Превышен предел издержек GC» - PullRequest
10 голосов
/ 19 мая 2010

Иногда, где-то между раз в 2 дня и раз в 2 недели, мое приложение вылетает в кажущемся случайном месте в коде с: java.lang.OutOfMemoryError: GC overhead limit exceeded. Если я погуглю эту ошибку, я приду к этому ТАКому вопросу , и это приведет меня к этой части документации по солнцу , которая истекает:

Параллельный сборщик сгенерирует ошибку OutOfMemoryError, если слишком много времени тратится на сборку мусора: если более 98% общего времени затрачивается на сборку мусора и восстанавливается менее 2% кучи, OutOfMemoryError будет брошен. Эта функция предназначена для предотвращения приложения работают в течение длительного периода времени, делая мало или нет прогресса, потому что куча слишком мала. При необходимости это эту функцию можно отключить, добавив параметр -XX: -UseGCOverheadLimit к командная строка.

Это говорит о том, что мое приложение, очевидно, тратит 98% общего времени на сборку мусора, чтобы восстановить только 2% кучи.

Но 98% какого времени? 98% всех двух недель приложение работало? 98% последней миллисекунды?

Я пытаюсь найти лучший подход к решению этой проблемы, а не просто использовать -XX:-UseGCOverheadLimit, но я чувствую необходимость лучше понять проблему, которую решаю.

Ответы [ 3 ]

6 голосов
/ 19 мая 2010

Я пытаюсь определить лучший подход к решению этой проблемы, а не просто -XX:-UseGCOverheadLimit, но мне нужно лучше понять проблему, которую я решаю.

Ну, вы используете слишком много памяти - и, судя по всему, это из-за медленной утечки памяти.

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

Чтобы выяснить, является ли это утечкой памяти, попросите виртуальную машину выгрузить кучу на OOM с помощью переключателя -XX:+HeapDumpOnOutOfMemoryError, а затем проанализируйте дамп кучи, чтобы увидеть, существует ли больше объектов какого-либо типа, чем должно быть. http://blogs.oracle.com/alanb/entry/heap_dumps_are_back_with - неплохое место для старта.


Редактировать: Как бы то ни было, судьба сама столкнулась с этой проблемой через день после того, как этот вопрос был задан, в пакетном приложении. Это не было вызвано утечкой памяти, и увеличение размера кучи также не помогло. На самом деле я уменьшил размер кучи (с 1 ГБ до 256 МБ), чтобы ускорить полный сборщик мусора (хотя и несколько чаще). YMMV, но оно того стоит.

Редактировать 2: Не все проблемы решаются с помощью кучи меньшего размера ... следующим шагом было включение G1 сборщика мусора , который, кажется, работает лучше, чем CMS.

1 голос
/ 30 июля 2012

Но 98% какого времени?98% всех двух недель приложение работало?98% последней миллисекунды?

Простой ответ: он не указан.Однако на практике эвристика «работает», поэтому она не может быть любой из двух крайних интерпретаций, которые вы выдвинули.сделаны, вы всегда можете прочитать исходный код OpenJDK 6 или 7.Но я бы не стал беспокоиться, потому что это не помогло бы вам решить вашу проблему.

«Лучший» подход - это немного почитать о настройке (начиная со страниц Oracle / Sun), а затем осторожно «вертеть ручки настройки».Это не очень научно, но проблемное пространство (точно прогнозирование приложение + производительность GC) "слишком сложно", учитывая инструменты, доступные в настоящее время.

1 голос
/ 19 мая 2010

> 98% будет измеряться за тот же период, когда восстанавливается менее 2% памяти.

Вполне возможно, что для этого нет фиксированного периода. Например, если проверка OOM будет выполняться после каждых 1 000 000 проверок объекта. Время, которое требуется, будет зависеть от машины.

Скорее всего, вы не сможете "решить" вашу проблему, добавив -XX:-UseGCOverheadLimit. Наиболее вероятным результатом является то, что ваше приложение будет медленно сканироваться, использовать немного больше памяти, а затем достигнет точки, когда GC просто больше не восстанавливает любую память. Вместо этого исправьте утечки памяти, а затем (если это необходимо) увеличьте размер кучи.

...