这个坑值得记一笔。监控显示接口每隔几秒出现一次明显停顿,GC 日志里完整回收次数持续增长,堆使用率并不高。
这类报错背后常见的原因有几处,逐个排除就行。元空间或者直接内存不足,触发完整回收;显式调用了回收方法;新生代太小,对象过早晋升到老年代。
第一件事是看回收次数和耗时
jstat -gcutil $(pidof java) 1000 10
然后确认元空间使用
jstat -gcmetacapacity $(pidof java)
调大新生代与元空间
grep -n -E 'Xmn|MetaspaceSize' /opt/app/start.sh
剩下的就是观察停顿是否消失
grep -c 'Full GC' /var/log/app/gc.log
同事提醒我看一下最近一次发布,时间点确实对得上。
命令输出我都留了记录,免得改完记不清原来的值。
改之前先确认了最近有没有人动过配置,避免白查一遍。
改完先别撤,确认这几项。完整回收频率降到每小时个位数,接口停顿消失,响应时间稳定。
补一句。只看堆使用率会漏掉元空间和直接内存,这两块不足同样会触发完整回收。改动前把原配置备份一份,出问题能马上回滚,这比任何技巧都实用。