У меня проблема с памятью в службе Java (21), использующей среду Spring (3.2.1).
Сервис довольно простой. Он предоставляет конечную точку REST.
Когда вызывается эта конечная точка, служба отправляет HTTP-запрос другой службе (используя механизм RESTCLIENT Spring) для получения данных. Как только данные получены, они возвращаются.
Данных много, поэтому, когда я звоню на свою конечную точку, происходит всплеск использования памяти, что меня не удивляет.
Однако после завершения обработки объем памяти остается высоким и никогда не отключается.
Вот скриншот из VisualVM:
Память остается высокой, пока я не нажму «Выполнить сбор мусора» в VisualVM. Я пробовал, даже через 24 часа память все еще остается высокой, даже если никто не звонит на мою конечную точку.
Вот дополнительная информация:
Есть ли у вас какие-либо идеи о происхождении проблемы и возможных решениях?
Это нормальное поведение. Сборщики мусора Java предназначены для минимизации двух показателей:
Минимизация общего использования памяти не является основной целью.
В вашем примере вы используете G1GC с (явной или неявной) целью максимального времени паузы. JVM видит, что еще есть ~1 ГБ свободного места в куче, и оценивает, что ей еще не нужно запускать сборщик мусора, чтобы обеспечить соблюдение гарантий времени паузы. Так что это не так... потому что запуск сборщика мусора, когда мусора недостаточно, неэффективен.
Честно говоря, я не думаю, что это вообще проблема. Но если среднее использование памяти действительно является для вас проблемой, обратите внимание на варианты G1PeriodicGC
. Они сообщают JVM периодически запускать сборщик мусора при условии, что JVM еще не (слишком) занята. Подробности см. JEP 346. Эта функция была реализована в Java 12, поэтому она должна быть доступна в образе Java 21, который вы (я думаю) используете.
Примечание: