1.MAT分析
第一时间获取内存快照,使用MAT工具进行分析
发现有个120M的大对象
对这个大对象进行分析发现,内存溢出位置发生于ThreadLocal,里面存了一个Map,对应的值都是
SessionInMemory
2.查找对应代码
发现该对象的位置是位于shiro-redis插件,找到该对象的使用位置发现
这里不断的put数据进去,导致内存溢出
3.原因
由于tomcat存在线程池,然后该插件作者为了提高性能,使用了ThreadLocal,然后维护的是一个Map对象,然而这个线程不会销毁,所以ThreadLocal一直存在,GC也无法使其回收
4.解决
更换shiro-redis的版本,从2.8.24升级到3.2.3
新版本的修复
作者添加了一行移除SessionInMemory的操作
5.监控
5个小时内存几乎没有变化
产生了373次YGC,年老代占用11.15%