如何防止Java超出容器内存限制? [英] How to prevent Java from exceeding the container memory limits?

查看:69
本文介绍了如何防止Java超出容器内存限制?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在Docker容器内运行Java程序,该容器的硬盘内存限制为4GB.我将最大堆设置为3GB,但Java程序仍然超出了限制并被杀死(OOMKilled).

I'm running a Java program inside a Docker container that has a hard memory limit of 4GB. I've set the max heap to 3GB but still the Java program exceeds the limit and gets killed (OOMKilled).

我的问题是:如何配置Java以遵守设置的容器限制并抛出OutOfMemoryException,而不是尝试分配超出限制并被主机内核踢走?

My question is: How can I configure Java to respect the set container limit and throw an OutOfMemoryException instead of trying to allocate beyond the limit and get its ass kicked by the host kernel?

更新:我是一位经验丰富的Java开发人员,对JVM有一定的了解.我知道如何设置最大堆,但是我想知道是否有人知道设置JVM进程从OS声明的内存限制的方法.

Update: I'm an experienced Java developer and have a fair understanding of the JVM. I know how to set the max heap, but I wonder if anyone knows of a way to set a limit to the total memory that the JVM process claims from the OS.

推荐答案

在容器内执行Java应用程序时,JVM人机工程学(负责根据主机的功能动态分配资源)不知道它正在运行在容器内部,并根据执行容器的主机计算Java应用程序要使用的资源数量.鉴于此,您是否对容器设置限制都没有关系,JVM将以您主机的资源为基础进行计算.

When a Java application is executed inside a container, the JVM ergonomics (which is responsible for dynamically assign resources based on the host's capabilities) does not know it is running inside a container and it calculates the number of resources to be used by the Java app based on the host that is executing your container. Given that, it does not matter if you set limits to your container, the JVM will take your host's resources as the base for doing that calculation.

在JDK 8u131 +和JDK 9中,有一个实验性的VM选项,该选项允许JVM人机工程学从CGgroup读取内存值.要启用它,您必须将以下标志传递给JVM:

From JDK 8u131+ and JDK 9, there’s an experimental VM option that allows the JVM ergonomics to read the memory values from CGgroups. To enable it you must pass the following flags to the JVM:

-XX:+ UnlockExperimentalVMOptions和-XX:+ UseCGroupMemoryLimitForHeap

-XX:+UnlockExperimentalVMOptions and -XX:+UseCGroupMemoryLimitForHeap

如果启用这些标志,则JVM将知道该容器正在容器中运行,并将使JVM符合人体工程学,从而根据容器限制而不是主机的能力来计算应用程序的资源.

If you enable these flags, the JVM will be aware that is running inside a container and will make the JVM ergonomics to calculate the app's resources based on the container limits and not the host's capabilities.

启用标志:

$ java -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -jar app.jar

您可以使用ENV变量将JVM选项动态传递给您的容器.

You can dynamically pass the JVM options to your container with ENV variables.

示例:

运行您的应用程序的命令类似于:

The command to run your app would like something like:

 $ java ${JAVA_OPTIONS} -jar app.jar

docker run 命令需要像这样传递ENV变量:

And the docker run command needs to pass the ENV variable like this:

$ docker run -e JAVA_OPTIONS="-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap" myJavaImage

希望这会有所帮助!

这篇关于如何防止Java超出容器内存限制?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆