我正在 Docker 容器内运行 Java 程序,该容器的硬内存限制为 4GB。我已将最大堆设置为 3GB,但 Java 程序仍然超出限制并被杀死 (OOMKilled)。
我的问题是:如何配置 Java 以尊重设置的容器限制并抛出 OutOfMemoryException,而不是尝试分配超出限制并被主机内核踢掉?
Update:我是一名经验丰富的 Java 开发人员,对 JVM 有一定的了解。我知道如何设置最大堆,但我想知道是否有人知道如何设置限制totalJVM 进程从操作系统请求的内存。
当 Java 应用程序在容器内执行时,JVM 人体工程学(负责根据主机的功能动态分配资源)不知道它正在容器内运行,它会计算 Java 应用程序要使用的资源数量基于正在执行容器的主机。鉴于此,无论您是否对容器设置限制,JVM 都会以主机的资源作为进行计算的基础。
从 JDK 8u131+ 和 JDK 9 开始,有一个实验性 VM 选项,允许 JVM 人体工程学从 CGgroup 读取内存值。要启用它,您必须将以下标志传递给 JVM:
-XX:+UnlockExperimentalVMOptions 和 -XX:+UseCGroupMemoryLimitForHeap
如果启用这些标志,JVM 将知道正在容器内运行,并使 JVM 符合人体工程学,根据容器限制而不是主机的功能来计算应用程序的资源。
启用标志:
$ java -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -jar app.jar
您可以使用 ENV 变量将 JVM 选项动态传递到容器。
Example:
运行应用程序的命令类似于:
$ java ${JAVA_OPTIONS} -jar app.jar
And the 码头运行命令需要传递 ENV 变量,如下所示:
$ docker run -e JAVA_OPTIONS="-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap" myJavaImage
希望这可以帮助!
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)