Можно ли получить OutOfMemoryError, потому что сбор мусора слишком медленный?

В java, возможно ли, что вы получаете исключение OutOfMemoryError, даже если у вас должно быть достаточно памяти, чтобы сбор мусора освободил больше памяти? Другими словами, если памяти недостаточно для выделения, будет ли gc принудительно запускаться, прежде чем выбросить OutOfMemoryError?

Спасибо.

Ответ 1

Существует один случай, когда вы можете получить OOM, который не связан ни с кучей, ни с адресным пространством: это когда JVM решает, что GC занимает слишком много времени для запуска.

Смотрите здесь.

Другими словами, ответ на ваш исходный вопрос, то есть "если памяти недостаточно, чтобы выделить, будет ли gc принудительно запускаться перед выбросом OutOfMemoryError", да.

(вы увидите по ссылке выше, что коэффициент составляет 98%/2% для кода gc/running, который очень высок)

(примечание 2: это для Sun/Oracle JVM, нет идеи для других реализаций)

Ответ 2

вы можете получить его, если GC проводит слишком много времени, пытаясь освободить память, а не освободить много памяти, сделав так: "java.lang.OutOfMemoryError: превышение верхнего предела GC", см. этот вопрос.

Ответ 3

GC принудительно запускается до вывода OutOfMemoryError. Если JVM реализует несколько разновидностей GC (например, "параллельный" или "частичный" ), GC "остановит мир" будет запущен до того, как JVM отступит, поэтому были предприняты все возможные усилия, чтобы избежать ошибки.

Исключением является то, что если GC неоднократно запускается и восстанавливает только минимальный объем хранилища (и размер кучи не может быть дополнительно расширен), то он будет перебрасываться в полотенце, а не продолжать работать в режиме "обхода". Теоретически, для этого случая, слегка увеличивая размер кучи, "хорошее" приложение будет работать нормально, но приложение, которое медленно пережевывает кучу (что не является необычным), не принесет пользы от небольшого увеличения кучи и столкнется с с той же ошибкой чуть позже.

[Следует отметить, что в случаях, когда GC работает слишком часто, увеличение размера кучи может значительно снизить накладные расходы GC, , если приложение хорошо себя ведет и, по случайному совпадению, работает около ограничение кучи. (Конечно, увеличение размера кучи до большей, чем доступная оперативная память, обычно замедляет работу приложения.)]

Ответ 4

Кажется, что если вы напишете соответствующий код, вы никогда не ударите OOM. Поскольку JVM будет запускать gc, прежде чем он попадет в OOM.

Итак, если вы нажмете OOM, скорее всего, ваш код получит утечку памяти. Проверьте это.

http://www.ibm.com/developerworks/library/j-leaks/

Ответ 5

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

Это очень исключение (не каламбур), а не правило, хотя вы почти никогда не пытаетесь спровоцировать сборку мусора самостоятельно.