监控显示某服务常驻内存每天都涨两百 M 左右,重启就归零,怀疑是泄漏,但说不清到底是哪一段在涨。

真正麻烦的地方在于,几个原因的现象几乎一样。应用内的缓存没有上限,随请求量一直累积;连接或者文件句柄没有释放,连带缓冲区一起增长;第三方库的本地内存分配没有归还给系统。

动手时先看进程内存分布

pmap -x $(pidof app) | tail -20

接着按时间对比堆与匿名段

grep -E 'Rss|Anon' /proc/$(pidof app)/status

取两次对象直方图做对比

jmap -histo:live $(pidof java) | head -30

等前面都确认过,再确认句柄数量是否同步增长

ls /proc/$(pidof app)/fd | wc -l

同样的操作我在测试机上先走了一遍,线上只做验证过的部分。

恢复的判定其实很直接。定位到具体对象后修复,连续观察三天内存曲线走平,不再单调上涨。

常驻内存涨不一定都是泄漏,内存池释放后也不归还系统;要看长期趋势并结合业务量做对比。报错文案容易误导,真正的原因往往在相邻那一层的日志里。

作者 9823189