Начиная с Java 8u131, есть возможность установить ограничения JVM на основе ограничений памяти контейнера .Поэтому, если вы запустите что-то вроде:
docker run \
-m 2g \ # set a container memory limit
openjdk:8 \
java \
-XX:+UnlockExperimentalVMOptions \
-XX:+UseCGroupMemoryLimitForHeap \
com.example.Classname
, JVM установит ограничение кучи так, чтобы оно соответствовало пределу памяти контейнера в 2 ГБ, выполнив для вас -Xmx
.В принципе, это должно устроить так, что вы никогда не достигнете предела памяти контейнера, а получите сначала Java OutOfMemoryError
.
В этом посте есть еще пара примеров на эту тему, итакже предлагает -XX:MaxRamFraction=1
разрешить использование «всей памяти», где вы ограничены этим с помощью опции docker run -m
.
На практике вы, вероятно, установите $JAVA_OPTS
в Dockerfile, например
FROM openjdk:8
COPY app.jar /
ENV JAVA_OPTS=-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRamFraction=1
CMD ["java", "-jar", "/app.jar"]
и затем запустите его как
docker run -d -p ... -m 2g myimage
В среде Kubernetes объявленный предел памяти в ограничениях ресурсов модуля играет ту же роль.
Как подсказывает @KarolDowbecki в своихответ, вам нужно сделать некоторые профилирование и мониторинг, чтобы на самом деле выбрать правильный номер для этого.Запуск приложения локально и мониторинг статистики RSS
(размер резидентного набора) в ps
или top
должны дать вам разумный базовый уровень.