Hibernate内存溢出分析一例
2016-04-11 14:47
274 查看
公司业务系统在进行压力测试时,压测24小时后系统发生内存溢出。经过分析读dump文件,发现org.hibernate.stat.StatisticsImpl类的hashmap类型的变量存储了大量数据(3百多万条),此成员变量消耗了2g的内存。如下图:
org.hibernate.stat.StatisticsImpl类是性能统计的功能实现,当hibernate.generate_statistics配置为true时就会启用此功能。因此此功能在生产环境下必须关闭,否则此处消耗的系统资源会影响系统性能并且最终会发生oom。
org.hibernate.stat.StatisticsImpl的源代码:
即以查询的sql或hql作为queryStatistics的key,此map的数量量过大说明查询的sql或hql语句的查询条件不是变量绑定或预编译的写法,在进行大量的动态sql、hql查询时就会导致此问题。
从此次问题也说明以下两点很重要:
在编写sql、hql是应采用变量绑定或预编译的写法(如where id=?或where id=:id),避免出现大量不同的sql语句。如未遵循这个规则,在数据库中也会发生比较高的硬简析。
hibernate.generate_statistics的功能在生产环境应禁用。
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是应采用变量绑定或预编译的写法(如where id=?或where id=:id),避免出现大量不同的sql语句。如未遵循这个规则,在数据库中也会发生比较高的硬简析。
hibernate.generate_statistics的功能在生产环境应禁用。
相关文章推荐
- JAVA 多线程随笔 (三) 多线程用到的并发容器 (ConcurrentHashMap,CopyOnWriteArrayList, CopyOnWriteArraySet)
- 分页
- lintcode:交错正负数
- Orthographic camera-正交摄像头
- 11个人气超高的设计素材汇总网站
- pat1002
- web Android手机调试chrome://inspect/
- YTUOJ之最快合并链表(线性表)
- jstl varStatus 计数
- JAVA学习---集合系列---PriorityQueue
- 作业4:结对编程项目四则运算
- 动态规划3-------poj1050
- Jackson 高性能的JSON处理 ObjectMapper
- 数据仓库之三种事实表
- 关于deselectRowAtIndexPath
- UVA103动态规划之DAG上的最长路及其字典序
- <css 十一>relative相对定位、absolute绝对定对
- github添加远程仓库报错:fatal: remote origin already exists.
- mysql数据库
- [C++日常小题] 三角螺旋数组