如果容器資源沒有設定任何
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
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
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,不建議這麼做,需要給其他程式預留部分記憶體