Вызовите полную сборку "мусора", когда размещение памяти пойдет вне определенного порога

У меня есть серверное приложение, которое, в редких случаях, может выделить большие блоки памяти.

Это не утечка памяти, поскольку эти блоки могут требоваться возвратить сборщиком "мусора" путем выполнения полной сборки "мусора". Нормальная сборка "мусора" освобождает объемы памяти, которые являются слишком маленькими: это не соответствует в этом контексте.

Сборщик "мусора" выполняет эти полные GCs, когда он считает соответствующим, а именно, когда объем потребляемой памяти приложения приближается к выделенному максимуму, указанному с-Xmx.

Это было бы в порядке, если бы это не было для того, что эти проблематичные выделения памяти происходят в пакеты и могут вызвать OutOfMemoryErrors вследствие того, что jvm не может выполнить GC достаточно быстро для освобождения необходимой памяти. Если я вручную называю System.gc () заранее, я могу предотвратить эту ситуацию.

Так или иначе я предпочел бы не иметь необходимость контролировать выделение памяти своего jvm сам (или вставить управление памятью в логику моего приложения); было бы хорошо, если бы был способ выполнить виртуальную машину с порогом памяти, по которому полный GCs был бы выполнен автоматически для выпуска очень рано памяти, в которой я испытываю необходимость.

Длинная короткая история: Мне нужен путь (параметр командной строки?) для конфигурирования jvm, чтобы выпустить рано хороший объем памяти (т.е. выполнить полный GC), когда размещение памяти достигает определенного порога я не забочусь, замедляет ли это мое приложение время от времени.

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

Я ценил бы Ваши предложения,

Silvio

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

ОБНОВЛЕНИЕ: анализируя приложение с jvisualvm, я вижу, что проблема находится в старом поколении

10
задан Silvio Donnini 16 March 2010 в 10:12
поделиться

7 ответов

Из здесь (это страница 1.4.2, но такая же опция должна существовать во всех JVM Sun ):

предполагая, что вы используете сборщик мусора CMS (который, как я полагаю, сервер включается по умолчанию), вам нужен вариант

-XX:CMSInitiatingOccupancyFraction=<percent>

, где% - это% используемой памяти, запускающей полный сборщик мусора.

Вставьте сюда стандартные заявления об отказе от ответственности, что неправильное использование параметров GC может привести к серьезным проблемам с производительностью, сильно зависит от машины и т. Д.

7
ответ дан 3 December 2019 в 23:12
поделиться

Здесь есть очень подробное объяснение того, как работает сборщик мусора , здесь и перечислены параметры для управления памятью, доступной для различных пулов / поколений памяти.

1
ответ дан 3 December 2019 в 23:12
поделиться

Когда вы выделяете большие объекты, которые не подходят молодому поколению, они немедленно выделяются в закрепленном пространстве поколения. Это пространство используется только при запуске полного сборщика мусора, который вы пытаетесь принудительно выполнить.

Однако я не уверен, что это решит вашу проблему. Вы говорите: «JVM не может достаточно быстро выполнить сборку мусора». Даже если ваши выделения идут пачками, каждое выделение заставит виртуальную машину проверять, достаточно ли у нее места для этого. В противном случае - и если объект слишком велик для молодого поколения - это вызовет полный сборщик мусора, который должен «остановить мир», тем самым в первую очередь не допуская новых распределений. Как только сборщик мусора будет завершен, ваш новый объект будет выделен.

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

Вы говорите: «Мне нужен способ [...] заблаговременно освободить хороший объем памяти (т.е. выполнить полный сборщик мусора), когда занятость памяти достигает определенного порога». Это по определению может быть успешным только в том случае, если на этот «хороший объем памяти» больше ничего не ссылается в вашем приложении.

Насколько я понимаю, у вас может быть состояние гонки, которого иногда можно избежать, перемежая ручные запросы GC. В общем, вам никогда не следует беспокоиться об этих вещах - по моему опыту OutOfMemoryError возникает только в том случае, если на самом деле слишком много выделений для одновременного размещения в куче. Во всех других ситуациях «единственной» проблемой должно быть снижение производительности (которое может стать экстремальным, в зависимости от обстоятельств, но это другая проблема).

Я предлагаю вам провести дальнейший анализ конкретной проблемы, чтобы исключить это. Я рекомендую инструмент VisualVM, поставляемый с Java 6. Запустите его и установите подключаемый модуль VisualGC. Это позволит вам увидеть различные поколения памяти и их размеры. Также существует множество вариантов ведения журнала, связанных с GC, в зависимости от того, какую виртуальную машину вы используете. Некоторые варианты были упомянуты в других ответах.

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

Когда вы будете более уверены в том, что на самом деле происходит, найти решение станет проще.

4
ответ дан 3 December 2019 в 23:12
поделиться

Вы пробовали играть с G1 gc? Он должен быть доступен начиная с версии 1.6.0u14.

0
ответ дан 3 December 2019 в 23:12
поделиться

Знаете ли вы, какой из пулов сбора мусора становится слишком большим? .... т.е. рай против космоса выжившего? (попробуйте опцию JVM -Xloggc: записать статус GC в файл с отметками времени ) ... Когда вы это знаете, вы сможете настроить размер пула с одним из параметры, упомянутые здесь: параметры точки доступа для Java 1.4

Я знаю, что эта страница предназначена для JVM 1.4, я не могу найти те же параметры -X в моих текущих параметрах справки по установке 1.6, если только эти индивидуальные настройки размеры бассейна - нестандартная, нестандартная особенность!

1
ответ дан 3 December 2019 в 23:12
поделиться

Попробуйте использовать параметр -server. Это включит параллельный gc, и у вас будет некоторое увеличение производительности, если вы используете многоядерный процессор.

0
ответ дан 3 December 2019 в 23:12
поделиться

Предполагается, что JVM выдает ошибку OutOfMemoryError после того, как пытается освободить память с помощью сборки мусора (согласно обоим документация API для OutOfMemoryError и спецификация JVM ). Поэтому ваши попытки принудительно вывести мусор не должны иметь никакого значения. Так что здесь может происходить что-то более существенное - либо проблема с вашей программой, не очищающая ссылки должным образом, либо, что менее вероятно, ошибка JVM.

1
ответ дан 3 December 2019 в 23:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: