机器:2C4G
程序:用户同步程序
现象:2023.9.15~2023.9.18之间,只要启动全量同步,10分钟内就会发生内存泄漏
排查:
1.代码查看。经查看,代码有Map引用,用于数据比较,使用后并清除,正常
2.线程排查。经查看,线程只启动了3个同步线程,线程正常范围
3.使用jmap 查看内存分布
- jmap -histo:live 16372 > 16372.txt
- 主要对象是hashMap\$Node和org.hibernate.hql.internal.ast.tree.Node
4.使用jmap把内存dump下来分析
- jmap -dump:format=b,file=/tmp/memory_dump.hprof 16372
- 可以看出来主要对象是org.hibernate.internal.SessionFactoryImpl,占用已超2G
- org.hibernate.engine.query.spi.QueryPlanCache
5.分析
从内存分布和内存快照来看,基本上可以确定,溢出原因就是org.hibernate.internal.SessionFactoryImpl这个类中的org.hibernate.engine.query.spi.QueryPlanCache导致
查阅相关文档, hibernate有缓存机制,主要是QueryPlanCache。查询执行过程中会先去queryPlanCache中获取,如果没有才会去查询库,然后查询和结果值放queryPlanCache中。
在queryPlanCache中由org.hibernate.internal.util.collections.BoundedConcurrentHashMap实现,capacity默认为2048,也就是缓存最大查询计划数为2048,那只需要把capacity这个缓存查询数变小即可
6.修复和运行查看
把程序配置上加上以下配置后再运行
- spring.jpa.properties.hibernate.query.plan_cache_max_size=512
- spring.jpa.properties.hibernate.query.plan_parameter_metadata_max_size=32
- 结果如下图,也无内存溢出