#java #garbage-collection
#java #сбор мусора
Вопрос:
Я получил
java.lang.OutOfMemoryError: GC overhead limit exceeded
при разделении некоторых строк. Интересно, что ни память не была израсходована, ни сборщик мусора не сходил с ума:
Исключение появилось в 11:10, когда Eclipse заморозил программу перед фактическим выбросом исключения. Так что все после 11:10 может быть просто шумом.
Я неоднократно сталкивался с этой проблемой в своей давно запущенной программе, но я не знаю, как ее избежать. Даже выделение гораздо большего объема памяти только задерживает, но не останавливает его.
Комментарии:
1. Вы пробовали запускать,
-XX: HeapDumpOnOutOfMemoryError
а затем проверять дамп?2. У меня есть дамп, но на самом деле я не знаю, что искать.
3. Хм … например, необычно большое количество экземпляров объектов для класса, где вы этого не ожидаете. Но есть кое-что еще, что вы можете сделать: поместить исключение
OutOfMemoryError
. Теперь, когда происходит ООМ, у вас есть не только соответствующая трассировка стека, но и фактическое использование отладчика для проверки входных параметров и т. Д. В момент сбоя.4. У вас есть объяснение количества потоков, взрывающихся примерно в 10: 12?
5. Нет. Это либо какой-то артефакт JVisualVM-Eclipse-Connection после исключения, либо что-то неизвестное. Но это определенно произошло после того, как исключение было замечено Eclipse.
Ответ №1:
Вы используете сборку с остановкой мира (возможно, параллельная очистка).Это исключение связано с тем, что GC занимает слишком много времени, что может составлять более 98% от общего времени выполнения. В этом случае JVM завершает процесс, поскольку никакой реальной работы не выполняется.
Решения могут быть:
- Попробуйте другой тип GC, например, одновременную развертку по меткам, которая не является GC с остановкой мира;
- Попробуйте увеличить объем памяти, чтобы GC выполнялся не так часто;
- Игнорируйте это ограничение времени GC с помощью using
-XX:-UseGCOverheadLimit
, что может вызвать проблемы, поскольку JVM продолжает работать над GC вместо реальной работы; - Как уже упоминалось, выполните сброс трассировки памяти с
-XX: HeapDumpOnOutOfMemoryError
помощью и проанализируйте трассировку.
Немного больше объяснений, почему куча не заполнена, но GC превышает лимит (все это предположения, и для проверки причин требуется больше трассировок): это может быть
- слишком маленькое молодое поколение или большинство объектов выживают после незначительного GC, поэтому GC происходит слишком часто и / или тратит много времени на перемещение объектов (это может быть настроено путем изменения размера молодого поколения в куче или изменения скорости владения объектами с помощью некоторого флага JVM);
- слишком маленький размер старого поколения, который объекты сохранили из второстепенного GC, не может быть помещен в старое поколение, что приводит к частому большому GC (или полному GC кучи).