Hibernate内存溢出分析一例

文章详细分析了在使用Hibernate时,开启generate_statistics功能导致的内存溢出问题,通过深入理解org.hibernate.stat.StatisticsImpl类的工作原理,解释了为何在生产环境中该功能必须关闭。文章强调了在编写SQL、HQL语句时应采用变量绑定或预编译的方法来减少内存消耗,并提供了解决方案以避免系统性能下降和OOM错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

公司业务系统在进行压力测试时,压测24小时后系统发生内存溢出。经过分析读dump文件,发现org.hibernate.stat.StatisticsImpl类的hashmap类型的变量存储了大量数据(3百多万条),此成员变量消耗了2g的内存。如下图:

    

org.hibernate.stat.StatisticsImpl类是性能统计的功能实现,当hibernate.generate_statistics配置为true时就会启用此功能。因此此功能在生产环境下必须关闭,否则此处消耗的系统资源会影响系统性能并且最终会发生oom。

原理分析及总结

    进一步分析,org.hibernate.stat.StatisticsImpl的成员queryStatistice就是内存的溢出点:

    org.hibernate.stat.StatisticsImpl的源代码:

public class StatisticsImpl implements Statistics, StatisticsImplementor {

 

    /** entity statistics per query string (HQL or SQL) */

    private final Map queryStatistics = new HashMap();

 

//对此变量存储数据的方法:

public synchronized QueryStatistics getQueryStatistics(String queryString) {

        QueryStatistics qs = (QueryStatistics) queryStatistics.get(queryString);

        if (qs==null) {

            qs = new QueryStatistics(queryString);

            queryStatistics.put(queryString, qs);

        }

        return qs;

}

}

    即以查询的sql或hql作为queryStatistics的key,此map的数量量过大说明查询的sql或hql语句的查询条件不是变量绑定或预编译的写法,在进行大量的动态sql、hql查询时就会导致此问题。

 

从此次问题也说明以下两点很重要:

  1. 在编写sql、hql是应采用变量绑定或预编译的写法(如where id=?或where id=:id),避免出现大量不同的sql语句。如未遵循这个规则,在数据库中也会发生比较高的硬简析。
  2. hibernate.generate_statistics的功能在生产环境应禁用。

转载于:https://www.cnblogs.com/bingjava/p/5378408.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值