JVM 在容器环境的内存配置

如果容器资源没有设置任何 limits 并且Java没有设置额外参数的话,Java应用会默认使用宿主机 1/4 的内存作为 MaxHeapSize ,可通过如下命令验证:

$ docker run --rm -ti 129.0.4.40/common/jdk:8 java -XX:+PrintFlagsFinal -version | grep MaxHeapSize                                                                               uintx MaxHeapSize                              := 4164943872 

测试宿主机是16G内存,4164943872/1024/1024 ~ 4G

首先查看使用JDK版本是否支持 UseContainerSupport 参数,如果支持该参数,则JVM会自动读取容器限制的内存值,读取文件:/sys/fs/cgroup/memory/memory.limit_in_bytes

该参数在 Java 8u191+,10以及更高的版本中支持

$ docker run --rm -ti 129.0.4.40/common/jdk:8 java -XX:+PrintFlagsFinal -version | grep UseContainerSupport bool UseContainerSupport = true {product}

返回true则表示支持,没有任何返回表示不支持

 

 

支持 UseContainerSupport


实验使用的Java版本是

java version "1.8.0_202"Java(TM) SE Runtime Environment (build 1.8.0_202-b08)Java HotSpot(TM) 64-Bit Server VM (build 25.202-b08, mixed mode)使用 -XX:MaxRAMPercentage 参数来配置JVM可用容器限制的资源百分比,默认是25.0 取值范围是 0.0 到 100.0

$ docker run --rm -ti -m 2000m 129.0.4.40/common/jdk:8 java -XX:+PrintFlagsFinal -version | grep MaxHeapSize    uintx MaxHeapSize                              := 524288000    $ docker run --rm -ti -m 2000m 129.0.4.40/common/jdk:8 java -XX:MaxRAMPercentage=80.0 -XX:+PrintFlagsFinal -version | grep MaxHeapSize    uintx MaxHeapSize                              := 1677721600 

如上示例显示,如果容器限制了2000m的内存,默认JVM使用 1/4 的量,即500m

如果配置了 -XX:MaxRAMPercentage 参数,这里设置为80.0,表示JVM使用限制内存的80%,即1600m

建议值为75.0

 

 

不支持 UseContainerSupport


实验使用的Java版本是

java version "1.8.0_152"Java(TM) SE Runtime Environment (build 1.8.0_152-b16)Java HotSpot(TM) 64-Bit Server VM (build 25.152-b16, mixed mode)

使用 -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap 参数来让JVM读取容器限制

不过默认即使加上这两个参数,JVM也只会使用容器限制内存的 1/4 的量,可以再添加一个参数 -XX:MaxRAMFraction ,该参数表示使用可用内存的基数,默认是4

JVM可用最大heap内存=最大可用内存*1/MaxRAMFraction

$ docker run --rm -ti -m4000m 129.0.4.40/common/jdk:8.1 java -XX:+PrintFlagsFinal -version | grep MaxHeapSizeuintx MaxHeapSize                              := 4164943872
$ docker run --rm -ti -m4000m 129.0.4.40/common/jdk:8.1 java -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:+PrintFlagsFinal -version | grep MaxHeapSizeuintx MaxHeapSize                              := 1048576000                          
$ docker run --rm -ti -m4000m 129.0.4.40/common/jdk:8.1 java -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=2 -XX:+PrintFlagsFinal -version | grep MaxHeapSizeuintx MaxHeapSize                              := 2097152000

如上示例显示,如果容器限制了4000m的内存,默认JVM使用宿主机 1/4 的内存,即4G

如果配置了 -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap 参数,则JVM使用容器限制内存的 1/4,即4000m*1/4=1000m

如果配置了 -XX:MaxRAMFraction=2 ,则JVM使用容器限制内存的 1/2,即 4000m*1/2=2000m

设置 MaxRAMFraction 为1表示将容器所有内存分配给JVM,不建议这么做,需要给其他程序预留部分内存

Java 10 移除了 -XX:{Initial|Min|Max}RAMFraction 参数

对于 Java SE 8u121 以及之前的版本这些参数都不生效,只能通过 -Xms1000m -Xmx2000m 这种方式进行限制

-Xmx 参数即使设置了2000m,JVM也会分配比2000m多的内存,如果想将JVM完全限制在2000m以内,需要使用 -XX:MaxRAM 参数

おすすめ

転載: blog.csdn.net/qq_34556414/article/details/121101809