jmap -histo:live 1 | head -20 jcmd 1 GC.class_histogram | grep LinkedBlockingQueue
图片处理服务一到下午内存就涨,四小时从 1.2GB 到 6GB,Full GC 之后也降不下来,dump 里 LinkedBlockingQueue$Node 占了 3.4GB。先别急着动参数,把报错原文和时间点记下来,顺序反了容易白折腾。
原因不复杂,new LinkedBlockingQueue 不传容量时默认是 Integer.MAX_VALUE,提交速度超过消费速度,任务对象就一直在队列里堆着。队列持有任务引用,GC 回收不掉,堆只能一路往上走。
这次卡住的地方就在「无界队列内存上涨」这一环,单独把它拎出来验证,别和其他改动混在同一次发布里。动手前把原文件复制一份带时间戳,出问题立刻换回去,比现场分析快得多。
一次只改一处,改完立刻验证,几个改动叠在一起,出问题就说不清是谁导致的。
处理上按这个顺序:把队列换成有界容量 按峰值吞吐乘单任务耗时的两倍估;容量满了让拒绝策略显式报错 不要静默丢弃;给队列长度加指标 超过阈值告警;用 jmap 对比改前改后的对象占用。
改完只确认一件事:队列长度稳定在 500 以内,堆在两次 Full GC 后回到 1.5GB 附近。
