Когда приложение Java выполняется внутри контейнера, эргономика JVM (которая отвечает за динамическое назначение ресурсов на основе возможностей хоста) не знает, что оно выполняется внутри контейнера, и вычисляет количество ресурсов, которые будут использоваться приложением Java. на основе хоста, на котором выполняется ваш контейнер. Учитывая это, не имеет значения, устанавливаете ли вы ограничения для своего контейнера, JVM будет использовать ресурсы вашего хоста в качестве основы для выполнения этого расчета.
В JDK 8u131 + и JDK 9 есть экспериментальная опция виртуальной машины, которая позволяет эргономике JVM считывать значения памяти из групп CG. Чтобы включить его, вы должны передать JVM следующие флаги:
-XX: + UnlockExperimentalVMOptions и -XX: + UseCGroupMemoryLimitForHeap
Если вы включите эти флаги, JVM будет знать, что выполняется внутри контейнера, и сделает эргономику JVM для расчета ресурсов приложения на основе ограничений контейнера, а не возможностей хоста.
Включение флагов:
$ java -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -jar app.jar
Вы можете динамически передавать параметры JVM своему контейнеру с помощью переменных ENV.
Пример:
Команда для запуска вашего приложения должна выглядеть примерно так:
$ java ${JAVA_OPTIONS} -jar app.jar
И команда docker run должна передать переменную ENV следующим образом:
$ docker run -e JAVA_OPTIONS="-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap" myJavaImage
Надеюсь это поможет!
person
Fabian Rivera
schedule
27.08.2018
Error
, и маловероятно, что вы сможете снова встать на ноги послеOOME
. Чтобы JVM не использовала слишком много памяти, вам нужно уменьшить потребление памяти в вашем приложении или вам нужно обновить контейнер, выделив больше памяти. - person AxelH   schedule 27.08.2018java
. Обновления в комментариях не так заметны для будущих читателей. Спасибо! - person halfer   schedule 27.08.2018