服务运行一段时间后接口大面积超时,日志里出现堆内存溢出,重启后几分钟又复发。日志里能对上时间点,这种反而好排。
对象创建速度超过回收速度,或存在大对象长期被引用,堆空间被占满后无法再分配。这一点先确认清楚,后面就不用反复试。
java -Xms2g -Xmx2g -XX:+HeapDumpOnOutOfMemoryError \ -XX:HeapDumpPath=/data/dump -jar app.jar jmap -histo:live 12345 | head -20
这次卡住的地方就在「Java 堆内存溢出」这一环,单独把它拎出来验证,别和其他改动混在同一次发布里。先做最小复现,能稳定跑出来的问题,排查成本会低一个数量级。
别只看报错的最后一行,往上看几行,真正的起因通常在上面。同类问题如果隔一段时间又出现,多半是某个定时任务或重启流程把改动冲掉了。
把这次用到的命令存进笔记,比记住结论有用,换个环境还能照着走。
处理上按这个顺序:启动参数加上堆转储,溢出时自动落盘;用工具分析占用最大的对象;定位持有引用的集合或缓存。
结果对不对很好判断,调整后连续压测一小时不再出现堆溢出,GC 后老年代占用能回落。