本文介绍如何在容器环境下配置JVM堆参数大小。背景信息当您的业务使用Java开发,JVM堆空间设置过小时,程序可能会遇到系统内存OOM(OutofMemory)不足的问题。尤其是在容器环境下,不合理的JVM堆参数设置会导致各种异常现象,比如应用堆大小没有达到设定的阈值或者规格限制,导致OOM重启。使用-XX:MaxRAMPercentage限制堆大小(推荐)在容器环境下,Java只能获取服务器的配置,无法感知容器的内存限制。可以通过设置-Xmx来限制JVM堆大小,但是这种方法存在以下问题:规范大小调整后,需要重新设置堆大小参数。当参数设置不合理时,应用堆大小未达到阈值,容器OOM被强行关闭。说明当应用程序出现OOM问题时,会触发Linux内核的OOMKiller机制。该机制可以监测到占用内存过多的进程,尤其是瞬间消耗大量内存的进程,然后强行关闭某个进程,为系统腾出内存,避免系统立即崩溃。推荐JVM参数设置XX:+UseContainerSupport-XX:InitialRAMPercentage=70.0-XX:MaxRAMPercentage=70.0-XX:+PrintGCDetails-XX:+PrintGCDateStamps-Xloggc:/home/admin/nas/gc-${POD_IP}-$(date'+%s').log-XX:+HeapDumpOnOutOfMemoryError-XX:HeapDumpPath=/home/admin/nas/dump-${POD_IP}-$(date'+%s').hprof参数说明如下:parameter说明-XX:+UseContainerSupport使用容器内存。允许JVM从主机读取cgroup限制,例如可用的CPU和RAM,并进行相应的配置。当容器超出内存限制时,抛出OOM异常,而不是强行关闭容器。-XX:InitialRAMPercentage设置JVM使用的容器内存的初始百分比。建议与-XX:MaxRAMPercentage保持一致,推荐设置为70.0。-XX:MaxRAMPercentage设置JVM使用的容器内存的最大百分比。由于系统组件的开销,建议不要超过75.0,推荐设置为70.0。-XX:+PrintGCDetails输出GC细节。-XX:+PrintGCDateStamps输出GC时间戳。日期格式,如2019-12-24T21:53:59.234+0800。-Xloggc:/home/admin/nas/gc-${POD_IP}-$(date'+%s').logGC日志文件路径。需要保证Log文件所在的容器路径已经存在。建议将容器路径挂载到NAS目录,这样可以自动创建目录,持久化日志。-XX:+HeapDumpOnOutOfMemoryErrorJVM在OOM发生时自动生成一个DUMP文件。-XX:HeapDumpPath=/home/admin/nas/dump-${POD_IP}-$(date'+%s').hprofDUMP文件路径。需要保证DUMP文件所在的容器路径已经存在。建议您将容器路径挂载到NAS目录下,自动创建目录,实现日志的持久化存储。请注意,使用-XX:+UseContainerSupport参数需要JDK8u191+、JDK10及更高版本。JDK11下的日志相关参数-XX:+PrintGCDetails、-XX:+PrintGCDateStamps、-Xloggc:$LOG_PATH/gc.log已弃用。请改用参数-Xlog:gc:$LOG_PATH/gc.log。Dragonwell11目前不支持${POD_IP}变量。如果不挂载/home/admin/nas容器路径到NAS目录,应用启动前必须保证该目录存在,否则不会产生日志文件。通过-Xms-Xmx限制堆大小可以通过设置-Xms和-Xmx来限制堆大小,但是这种方法存在以下两个问题:规范大小调整后,需要重新设置堆大小参数。当参数设置不合理时,应用堆大小未达到阈值,容器OOM被强行关闭。说明当应用程序出现OOM问题时,会触发Linux内核的OOMKiller机制。该机制可以监测到占用内存过多的进程,尤其是瞬间消耗大量内存的进程,然后强行关闭某个进程,为系统腾出内存,避免系统立即崩溃。推荐JVM参数设置Xms2048m-Xmx2048m-XX:+PrintGCDetails-XX:+PrintGCDateStamps-Xloggc:/home/admin/nas/gc-${POD_IP}-$(date'+%s').log-XX:+HeapDumpOnOutOfMemoryError-XX:HeapDumpPath=/home/admin/nas/dump-${POD_IP}-$(date'+%s').hprof参数说明如下:参数说明-Xms设置JVM初始内存大小。建议与-Xmx相同,以避免JVM在每次垃圾收集完成后重新分配内存。-Xmx设置JVM的最大可用内存大小。为避免容器OOM,请为系统预留足够的内存大小。-XX:+PrintGCDetails输出GC细节。-XX:+PrintGCDateStamps输出GC时间戳。日期格式,如2019-12-24T21:53:59.234+0800。-Xloggc:/home/admin/nas/gc-${POD_IP}-$(date'+%s').logGC日志文件路径。需要保证Log文件所在的容器路径已经存在。建议您将容器路径挂载到NAS目录下,自动创建目录,实现日志的持久化存储。-XX:+HeapDumpOnOutOfMemoryErrorJVM在OOM发生时自动生成一个DUMP文件。-XX:HeapDumpPath=/home/admin/nas/dump-${POD_IP}-$(date'+%s').hprofDUMP文件路径。需要保证DUMP文件所在的容器路径已经存在。建议您将容器路径挂载到NAS目录下,自动创建目录,实现日志的持久化存储。Recommendedheapsize设置内存规格JVMheapsize1GB600MB2GB1434MB4GB2867MB8GB5734MB常见问题exitcode137对于容器意味着什么?当容器使用的内存超过限制时,就会发生容器OOM,导致容器被强制关闭。此时业务申请内存可能还没有达到JVM堆大小的上限,所以不会产生dump日志。建议您降低JVM堆大小的上限,为容器中的其他系统组件预留足够的内存空间。heapsize和specificationmemory的参数值可以一样吗?不能。由于系统组件有内存开销,JVM堆大小不能设置为与指定内存大小相同的值,必须为这些系统组件预留足够的内存空间。JDK8下设置-XX:MaxRAMPercentage为整数报错怎么办?这是JDK8的一个bug,详情参见JavaBugDatabase。比如在JDK8u191版本下,设置-XX:MaxRAMPercentage=70,则JVM启动会报错。解决方法如下:方法一:设置-XX:MaxRAMPercentage为70.0。注意如果使用-XX:InitialRAMPercentage或-XX:MinRAMPercentage,参数值不能设置为整数,必须按照方法一的形式设置。方法二:将JDK版本升级到JDK10或更高版本。
