Размер кучи Java используется не полностью

В настоящее время я отслеживаю свое работающее Java-приложение с помощью Visual VM: http://visualvm.java.net/

Я подчеркиваю использование памяти с помощью -Xmx128m.

При запуске я вижу, что размер кучи увеличивается до 128 м (как и ожидалось), однако используемая куча сходится примерно к 105 м, прежде чем я сталкиваюсь с ошибкой пространства кучи java.

введите здесь описание изображения

Почему эти оставшиеся 20м не используются?


person Will    schedule 04.05.2011    source источник
comment
Можете ли вы включить ошибку пространства кучи, которую вы получаете? Возможно дело в пермгене?   -  person Paul Whelan    schedule 04.05.2011
comment
У вас есть несколько куч, есть Eden Space, Survivor Space и Tenured Gen. И у вас не куча памяти. Может быть, в VisualVM есть фильтр. А для вашего приложения требуются эти 20 м?   -  person Thomas Jungblut    schedule 04.05.2011
comment
Я получаю java.lang.OutOfMemoryError: ошибка пространства кучи Java. что вы подразумеваете под ..фильтром в VisualWM..? В настоящее время я читаю большие файлы (всего около 100 МБ) и создаю карту для хранения определенной информации, поэтому я думаю, что мне нужно довольно много памяти.   -  person Will    schedule 05.05.2011
comment
Я не уверен, что здесь происходит. Обычно вы должны получить OutOfMemoryError, когда размер кучи составляет 120 МБ. Можете ли вы создать снимок приложения и отправить его мне? У вас есть воспроизводимый тестовый пример, которым вы можете поделиться? Я хотел бы взглянуть.   -  person Tomas Hurka    schedule 06.05.2011


Ответы (3)


Куча разделена на Young-Generation (Eden-Space и два Survivor-Spaces одинакового размера, обычно называемые From и To), Old Generation (Tenured) и Постоянное пространство.

Параметр Xmx/Xms задает общий размер кучи. Таким образом, регион (с размером по умолчанию) на самом деле является постоянным пространством — и, возможно, мы не знаем подробностей о вашем стресс-тесте, никакие объекты на самом деле не перемещаются из Эдема в постоянные или постоянные, поэтому эти регионы остаются пустыми, пока Эдем заканчивается. пространства.

person Andreas Dolk    schedule 04.05.2011
comment
Я думал, что perm gen хранится отдельно? - person Will; 05.05.2011
comment
@Will - я тоже, но потом я прочитал несколько статей, объясняющих, что параметр -Xmx настраивает полную кучу (включая PermGen), а другие флаги, такие как XX:MaxPermSize, настраивают внутреннюю структуру кучи. - person Andreas Dolk; 05.05.2011
comment
Спасибо, не могли бы вы предоставить мне ссылку на эту статью? - person Will; 05.05.2011
comment
Спасибо. Согласно статье, куча содержит файл PermGen. Так что, если бы VisualVm рассматривал PermGen не как используемое пространство (что не интуитивно понятно), мой вопрос был бы решен. - person Will; 09.05.2011

Вам нужно понять центральный факт об эргономике сборщика мусора:

Дорогостоящей частью сборки мусора является поиск и обработка объектов, которые НЕ являются мусором.

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

Чтобы избежать этой патологической ситуации, JVM отслеживает соотношение времени, затрачиваемого на сборку мусора и выполнение полезной работы. Когда соотношение превышает настраиваемое пороговое значение, сборщик мусора выдает OutOfMemoryError ... даже несмотря на то, что (технически) имеется свободная память. Это, вероятно, то, что вы видите, хотя другие объяснения столь же правдоподобны.

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

(На самом деле, вы используете его... но не все время.)

person Stephen C    schedule 04.05.2011
comment
Я не получаю сообщение об ошибке превышения лимита накладных расходов GC, а об ошибке пространства кучи java. - person Will; 05.05.2011
comment
Спасибо за вашу помощь, но, насколько я знаю, сценарий, который вы описываете в отношении порога GC, вызовет ошибку OutOfMemoryError: Превышен лимит накладных расходов GC. Однако я получаю сообщение об ошибке OutOfMemoryError: пространство кучи java. Поэтому я не думаю, что проблема заключается не в том, что сборщик мусора работает слишком долго и не требует достаточного количества памяти, а в том, что у меня по какой-то причине не хватает места в куче. - person Will; 05.05.2011
comment
Какой бы ни была причина, скорее всего, это утечка памяти, и именно на этом вы должны сосредоточиться, чтобы отследить и исправить. Тот факт, что приложение кажется не использует все эти 128 МБ памяти, не имеет значения. Даже если бы это было так, вы бы все равно умерли от утечки памяти… чуть позже. - person Stephen C; 05.05.2011
comment
И если у вас есть веские причины беспокоиться о потере 23 МБ памяти из-за накладных расходов сборщика мусора, вы, вероятно, выбрали неправильный язык реализации! - person Stephen C; 05.05.2011

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

person Peter Lawrey    schedule 04.05.2011
comment
Я не устанавливал никаких других параметров, кроме -Xmx128m. - person Will; 05.05.2011
comment
Вам нужно следить за разбивкой того, какие регионы заполняются. - person Peter Lawrey; 05.05.2011