商品详情接口 QPS 上来后老年代每小时涨 400MB,jmap 直方图里 ObjectMapper 有 12.6 万个实例,每个还带一份 SerializerCache。第一次遇到会往复杂处想,其实漏掉的多是个小前提。
jmap -histo:live 21455 | grep -i ObjectMapper
@Bean
public ObjectMapper objectMapper() { return new ObjectMapper(); }
ObjectMapper 内部缓存了序列化器和反序列化器,创建成本高、占用也不小。在方法里 new 等于每个请求都建一套缓存,用完只能等 GC。这一点先确认清楚,后面就不用反复试。
「ObjectMapper 内存」这个问题文档写得含糊,实际行为以当前版本为准,别照旧版本的结论套。临时改动用注释写上日期和原因,过两周自己都记不清为什么这么写。
动手前把原文件复制一份带时间戳,出问题立刻换回去,比现场分析快得多。一次只改一处,改完立刻验证,几个改动叠在一起,出问题就说不清是谁导致的。
具体做法是,改成 Spring 注入的单例 ObjectMapper;需要不同配置就建两三个命名 Bean 不要按请求建;确认没有地方 copy() 出新实例;用 histogram 对比改动前后的实例数。
改完照着核一遍,ObjectMapper 实例数降到个位数 老年代增长曲线变平。
