Почему это происходит?
По сути, есть две стратегии, которые JVM / GC может использовать, чтобы решить, когда следует отказаться от OOME.
Он может продолжать работать до тех пор, пока просто не будет достаточно памяти после сборки мусора для выделения следующего объекта.
Это может продолжаться до тех пор, пока JVM не потратит более определенного процента времени на работу сборщика мусора.
При первом подходе проблема заключается в том, что для типичного приложения JVM будет тратить все больший и больший процент времени на работу с GC, что в конечном итоге будет бесполезным усилием для выполнения задачи.
Второй подход заключается в том, что может сдаться слишком рано.
Фактическое поведение GC в этой области определяется параметрами JVM (-XX: ...). По-видимому, поведение по умолчанию отличается между 32- и 64-битными JVM. Этот вид имеет смысл, потому что (интуитивно) эффект «спирали смерти из памяти» для 64-битной JVM будет длиться дольше и будет более выраженным.
Мой совет - оставить этот вопрос в покое. Если вам действительно не нужно , чтобы заполнить каждый последний байт памяти чем-то, для JVM лучше умереть рано и не тратить много времени. Затем вы можете перезапустить его с большим объемом памяти и выполнить работу.
Очевидно, ваш эталонный тест нетипичен. Большинство реальных программ просто не пытаются захватить всю кучу. Вполне возможно, что ваше приложение тоже нетипично. Но также возможно, что ваше приложение страдает от утечки памяти. Если это так, вы должны исследовать утечку, а не пытаться выяснить, почему вы не можете использовать всю память.
Однако моя проблема в основном в том, почему он не соблюдает мои настройки xmx.
Это - это в честь этого! -Xmx - это верхний предел для размера кучи, а не критерий для принятия решения о том, когда следует отказаться.
Я установил XMX 2432M, но попросил JVM вернуть понимание максимальной памяти, возвращающей 2162M.
Возвращает максимальную память, которую она использовала , а не максимальную память , которую разрешено использовать .
Почему он «думает», что максимальный объем памяти на 11% меньше, чем у xmx?
См. Выше.
Кроме того, почему, когда куча достигает 2006M, она не расширяет кучу как минимум до 2162?
Я предполагаю, что это потому, что JVM достигла порога "слишком много времени, затрачиваемого на сборку мусора".
Означает ли это, что в 64-битных JVM следует изменить настройку XMX, чтобы она была на 11% выше предполагаемого максимума?
Не в общем. Коэффициент помадки зависит от вашего приложения. Например, приложение с большей скоростью оттока объектов (то есть больше объектов, созданных и отброшенных за единицу полезной работы), скорее всего, умрет с OOME раньше.
Я могу предсказать требования, основываясь на размере дБ, и иметь оболочку, которая регулирует xmx, однако у меня есть проблема 11%, из-за которой мой мониторинг предполагает, что приложению требуется 2 ГБ, поэтому я установил 2,4 ГБ xmx. однако вместо ожидаемых 400 МБ «запаса» jvm позволяет увеличить кучу только до 2006 млн.
IMO, решение состоит в том, чтобы просто добавить extra 20% (или более) поверх того, что вы добавляете в настоящее время. Предполагая, что у вас достаточно физической памяти, выделение JVM большей кучи уменьшит общие издержки GC и ускорит работу вашего приложения.
Другие хитрости, которые вы можете попробовать, - это установить -Xmx и -Xms в одно и то же значение и настроить параметр настройки, который задает максимальное соотношение времени, затрачиваемого на сборку мусора.