记一个内存泄漏问题:Query Plan Cache BoundedConcurrentHashMap占用堆内存

原因是hibernate会缓存sql语句以减少重复编译,便于直接命中提高效率。这个缓存默认最大值为2G (2024.05.08更正,queryPlanCache的map entry默认容量上限是2048,如果里面缓存的每个对象很大,则内存远超2G),且在使用in时,只要in后面的参数有任何一个不一样的,就会视为不同的语句而保存下来。
解决这个问题可以将缓存最大值改小。
我看大家都是这样写的:

spring:
  jpa:
    properties:
      hibernate:
        query:
          plan_cache_max_size: 64
          plan_parameter_metadata_max_size: 32
          plan_cache_max_soft_references: 1024
          plan_cache_max_strong_references: 64

实际上我在用spring boot的时候是这样写的:
(写入application.properties文件即可)

spring.jpa.properties.hibernate.query.plan_cache_max_size=128
spring.jpa.properties.hibernate.query.plan_parameter_metadata_max_size=64
spring.jpa.properties.hibernate.query.plan_cache_max_soft_references=1024
spring.jpa.properties.hibernate.query.plan_cache_max_strong_references=128

这里最重要的参数是plan_cache_max_size,把它设小之后就可以解决部分内存溢出问题。;

至于后面的强引用和软引用:
强引用是最普遍的引用,被引用的对象不会被垃圾回收器回收(还记得gc的对象吗)。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不回收这种对象。
软引用:只有在内存不足的时候JVM才会回收该对象。这个特性很适合用来实现缓存:比如网页缓存、图片缓存等。
所以开始的时候我的设想是软引用的值可以设大一点,因为在内存不足时会对此类对象进行回收。
在这里max_soft_references和max_strong_references的单位我并没有找到参考,到底是指M还是条数,但是却意外地发现这两个参数已经过时了,而且看起来是被上面的cache_max_size和parameter_metadata_max_size所代替了。
以下是org.hibernate.cfg.AvailableSettings这个类中的解释:
(eclipse快捷键下,ctrl+shitf+T可快速查找包中的类)

	/**
	 * The maximum number of soft references maintained by {@link org.hibernate.engine.query.spi.QueryPlanCache}. Default is 2048.
	 * @deprecated in favor of {@link #QUERY_PLAN_CACHE_MAX_SIZE}
	 */
	@Deprecated
	String QUERY_PLAN_CACHE_MAX_SOFT_REFERENCES = "hibernate.query.plan_cache_max_soft_references";

	/**
	 * The maximum number of strong references maintained by {@link org.hibernate.engine.query.spi.QueryPlanCache}. Default is 128.
	 * @deprecated in favor of {@link #QUERY_PLAN_CACHE_PARAMETER_METADATA_MAX_SIZE}
	 */
	@Deprecated
	String QUERY_PLAN_CACHE_MAX_STRONG_REFERENCES = "hibernate.query.plan_cache_max_strong_references";

所以实际上在设置的时候可能只需要设置:

spring.jpa.properties.hibernate.query.plan_cache_max_size=128
spring.jpa.properties.hibernate.query.plan_parameter_metadata_max_size=64

hibernate 5.2.17+时,还可以使用如下配置:

spring.jpa.properties.hibernate.query.in_clause_parameter_padding=true

开启后,只有第4,8,16,32等查询语句会被缓存。

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值