Подтвердить что ты не робот

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

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

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

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

enter image description here

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

Ответ 3

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

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

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

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

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

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