Java 云原生中的内存问题
- pod
- 4天前
- 23热度
- 0评论
为什么堆内存未超过 Xmx 却发生了 OOM?怎么理解操作系统和JVM的内存关系?为什么程序占用的内存比 Xmx 大不少,内存都用在哪儿了?为什么线上容器内的程序内存需求更大?
JVM的堆(Heap)占用内存过大会引发如下问题:如果JVM直接运行在Linux系统,可能会导致Java进程被Linux系统的OOM Killer所终止(Kill);如果JVM运行在Docker容器环境,可能会表现为频繁异常重启。本文针对在容器环境下运行JVM的内存配置给出建议,并解决OOM(Out of Memory)的相关常见问题。
推荐使用参数:-XX:MaxRAMPercentage限制JVM使用容器内存的最大百分比
容器环境下,推荐的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
注意事项:
-
使用
-XX:+UseContainerSupport
参数需JDK 8u191+、JDK 11及以上版本。 -
-XX:+UseContainerSupport
参数仅在部分操作系统上支持,具体支持情况请查阅您所使用的Java版本的官方文档。 -
在JDK 11及之后的版本中,日志相关的参数
-XX:+PrintGCDetails
、-XX:+PrintGCDateStamps
、-Xloggc:$LOG_PATH/gc.log
已被废弃,请使用参数-Xlog:gc:$LOG_PATH/gc.log
代替。 -
Dragonwell 11不支持
${POD_IP}
变量。 -
如果您没有将/home/admin/nas容器路径挂载到NAS目录,则必须保证该目录在应用启动前已存在,否则将不会产生日志文件。
参数说明:
参数 |
说明 |
|
设置JVM检测所处容器的内存大小和处理器数量,而不是检测整个操作系统的。 JVM会使用上述检测到的信息进行资源分配,例如: |
|
设置JVM使用容器内存的初始百分比。建议与 |
|
设置JVM使用容器内存的最大百分比。由于存在系统组件开销,建议最大不超过75.0,推荐设置为70.0,代表JVM最大使用容器内存的70%。 |
|
输出GC详细信息。 |
|
输出GC时间戳。日期形式,例如2019-12-24T21:53:59.234+0800。 |
|
GC日志文件路径。需保证Log文件所在容器路径已存在,建议您将该容器路径挂载到NAS目录或收集到SLS,以便自动创建目录以及实现日志的持久化存储。 |
|
JVM发生OOM时,自动生成Dump文件。 |
|
Dump文件路径。需保证Dump文件所在容器路径已存在,建议您将该容器路径挂载到NAS目录,以便自动创建目录以及实现日志的持久化存储。 |