Java кучи управления памятью недостаточно памяти - PullRequest
0 голосов
/ 03 июля 2018

Когда проект netty async server-client выполняется в linux, он исчерпывает всю доступную память, например так: linux console

Итак, я запускаю его на Windows, и JMC показывает кучу так:

JMC memory

Мои вопросы: почему windows и linux ведут себя по-разному, есть ли где-нибудь, где я мог бы настроить linux jvm для выпуска кучи памяти? А почему в windows (GC) есть куча релиза? Как найти подозрительный фрагмент кода, который занимает так много памяти?

РЕДАКТИРОВАТЬ : Linux - 4 ГБ, Windows - 8 ГБ, но я не думаю, что абсолютное значение вызывает различия в результатах работы. Project напрямую не обрабатывает необработанный байтовый буфер, он использует HttpServerCodec и HttpObjectAggregator для байтового буфера. Команда для запуска в Linux - java -jar xx.jar. Я хотел бы знать не только , почему разница, почему пилообразная , но также , как найти тот, который занимает столько памяти . JMC показывает другую цифру, и я не знаю, почему у потока может быть такой высокий номер блока. Нетто темы IO имеют 99LINE 71ms. JMC threads

ОБНОВЛЕНИЕ: Теперь я хотел бы определить, какая часть кода занимает столько памяти . Куча JMC показывает, что EDEN SPACE очень высока, и я обнаружил, что EDEN SPACE предназначен для new объекта. Первоначально в проекте использовался spring-boot с сервлетом tomcat 3.0 в качестве контейнера и пулом httpclient apache для клиента, теперь только эти части были изменены с помощью асинхронного сервера netty и асинхронного клиента netty, в то время как другие части остались (по-прежнему используется весна для управление бобами). Серверные и клиентские обработчики Netty являются общими для всех запросов (обработчики - это singleton spring bean). С такими небольшими изменениями, я не верю, что количество new объектов значительно увеличилось, что заканчивается 1,35 ГБ памяти JMC heap

ОБНОВЛЕНИЕ После отдельного запуска проектов netty и springboot я получаю больше статистических данных:

  1. Оперативная память 8G. Проект Springboot Edition: PS Old Generation: емкость = 195 МБ; б = 47MB; 24% использовали. И он имеет 692 971 объект с общим размером 41 848 384
  2. Оперативная память 16G. нетти версия проекта: PS Old Generation: емкость = 488 МБ; используется 327MB; 67% использовали. Он имеет 1 243 432 объекта с общим размером 221 427 824.

версия netty: дамп кучи показывает, что у него 279 255 экземпляров класса io.netty.buffer.PoolSubpage по сравнению со вторым по величине 7222 экземплярами класса org.springframework.core.MethodClassKey. Обе версии имеют ограниченные объекты обслуживания (нашего собственного класса), не более 3000.

Я пытался запустить с -Xmx1024m на 4G памяти Linux, все еще вызывает ту же проблему нехватки памяти.

1 Ответ

0 голосов
/ 03 июля 2018

Поведение, которое вы видите в Windows, является нормальным поведением GC. Приложение генерирует мусор, а затем вы достигаете порога, который заставляет GC работать. GC освобождает много кучи. И тогда приложение запускается снова. В результате образуется пилообразный шаблон в загруженности кучи.

Это нормально. Каждая JVM ведет себя примерно так или иначе.


Поведение в Linux выглядит так, будто что-то пытается выделить что-то большое (77 МБ) в собственной памяти и терпит неудачу, потому что ОС отказывается предоставить JVM такой большой объем памяти. Как правило, это происходит потому, что в ОС закончились ресурсы; например физическая оперативная память, пространство подкачки и т. д.

Windows 8G, Linux 4G.

Это, вероятно, объясняет это. Ваша система Linux имеет только половину физической памяти системы Windows. Если вы используете netty с большой кучей Java, а ваша ОС Linux не настроена ни на одно пространство подкачки, то вполне вероятно, что JVM использует всю доступную виртуальную память. Это может даже произойти при запуске JVM.

(Если мы предположим, что максимальный размер кучи был установлен одинаково как для Windows, так и для Linux, то в Windows доступно не менее 4,5 ГБ виртуального адресного пространства для других целей. В Linux - только 0,5 ГБ. 0,5 ГБ должны содержать все ресурсы JVM, не относящиеся к куче, а также ОС и различные другие процессы пользовательского пространства. Нетрудно понять, как вы могли бы использовать все это ... что привело к ошибке выделения.)

Если моя теория верна, то решением будет изменить параметры командной строки JVM, чтобы уменьшить -Xmx.

(Или увеличьте доступную физическую / виртуальную память. Но будьте осторожны с увеличением виртуальной памяти, добавляя пространство подкачки. Если соотношение виртуальной / физической памяти слишком велико, вы можете получить «перегрузку» виртуальной памяти, которая может привести к ужасной производительности. )

...