JDK8 G1 堆内存居然不释放

Rocky大约 4 分钟

背景

k8s环境中有个pod,pod里跑了一个java进程。 采用的是jdk版本是openjdk version "1.8.0_342"。 启动时有这些jvm参数:

-server 
-Dspring.datasource.druid.maxActive=80 
-XX:MaxGCPauseMillis=200 
-XX:+UseG1GC 
-XX:+UseContainerSupport 
-XX:MinRAMPercentage=20.0 
-XX:MaxRAMPercentage=70.0 
-Djava.security.egd=file:/dev/./urandom 
-Duser.timezone=GMT+08 
-XX:+HeapDumpOnOutOfMemoryError  
-XX:HeapDumpPath=/mnt/log 
-XX:+UnlockExperimentalVMOptions

depoyment的yaml文件中限制的内存是4g.

现在发现这个deployment的5个pod内存都占用了90%以上,且持续不降,部分pod还重启过3/4次

image.png
image.png

排查过程

怀疑存在内存泄漏或内存溢出

于是进入pod把堆dump下来,下载到本地分析。(由于是客户环境,没有权限直接操作k8s,只能访问dashborad面板,所以下载文件这个过程也是挺折腾的)

dump下来的堆文件确只有不到2g样子(有点纳闷,但没深究)

采用与博文 线上FullGC频繁的排查open in new window 排查方式分析堆文件,一无所获。

查看gc情况

image.png
image.png

可以看到,青年代发生了1.3万次gc,老年代没有发生过gc. (此时离pod启用有9天时间)

同时也能看到内存分配和使用情况:

  1. 堆内存: 使用了1.6g, committed2.8g内存(可以理解为jvm向操作系统申请了2.8g内存),最大堆内存限制为2.8g. (这个2.8就是deployment的4MaxRAMPercentage参数,也就是40.7=2.8)
  2. 非堆内存:包括直接内存、metaspace 、code cache 等。 使用了400m不到,committed400m内存。

然后很好奇的手动执行了一次fullgc,再看jvm情况,如下:

image.png
image.png

然后看k8s的dashboard

image.png
image.png

注意:因为这篇博文是事后写的,上面的图有些并不是同一个pod的信息,所以有些信息会对不上,但不影响问题分析。

可以看到堆内存的used和committed下降了,committed下降了大概1.3g样子,刚好就是dashboard上显示的内存差异,非堆内存几乎没有下降。

执行了fullgc后第二天,bashboard内存占用基本没有变动,没有再升上去

可以分析得出一个基本结论:

  1. 问题在堆内存,且代码可以基本排除内存泄漏或溢出的问题
  2. 青年代的gc 没有退还内存给操作系统,fullgc后退还了1.3g样子给操作系统

查资料,尝试增加jvm参数:

-XX:MaxHeapFreeRatio=30
-XX:MinHeapFreeRatio=10

-XX:MaxHeapFreeRatio=30 最大堆内存空闲比例,大致理解为jvm向操作系统了申请了2g内存,gc后只使用了1g. 那么空闲了1g,空闲比例就是50%,大于了30%,于是就会退还内存给操作系统。

-XX:MinHeapFreeRatio=10 同理,最小堆内存空闲比例,如果gc空闲比例小于了这个值,jvm就会向操作系统申请更多的内存

后面也尝试增加过其他参数

观察一段时间后,发现青年代gc后,还是没有减少committed内存。也没有增加老年代的gc次数

解决

其实算不上解决,或者解决得不够优雅。考虑到切换jdk版本,或者修改垃圾收集器可能产生意料之外的问题和成本,所以采用:

  • 周期性触发一次fullgc. 比如通过sidecar,或者linux的crontab或者代码定时任务等。

后文

后面再继续查资料,搜到一个类似问题的网址:

how-to-reduce-committed-heap-memory-in-jvmopen in new window

image.png
image.png

系统推荐









  • 随机毒鸡汤:说啥啥不听,干啥啥不行,吃啥啥不剩。

    Close-up of a rustic wooden wall featuring white numeric markings on a reddish-brown background.