`
xsh5324
  • 浏览: 70675 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Hibernate 一级缓存的陷阱

    博客分类:
  • java
阅读更多

最近公司的应用经常报OOM,一开始我以为是公司业务数据太多,导致内存不够,所以只是简单的把容器的内存加大。撑了几天后这个错仍然被报出来。后来我仔细分析过项目代码后,没有发现有任何引起内存泄漏的地方。百思不得其解,于是我决定在OOM异常发生的那刻将JVM内存堆导出来仔细分析,我在生产环境的某一台机器上加上了JVM启动参数:“-XX:+HeapDumpOnOutOfMemoryError

    -XX:HeapDumpPath=/app/vas_platform/temp/” 然后等了一天,终于又报错了,拿出堆文件用“Eclipse Memory Analyzer”打开分析,发现占用内存的地方居然有75%来自org.hibernate.engine.StatefulPersistenceContext(靠,这不科学啊!)

后来查看各个StatefulPersistenceContext里面的内容发现里面保存存着多达几十万个实体对象,其中大部分都是比较大的对象(本身字段特别多而且还级联了许多其它的实体一级接着一级的级联),心想为什么会这样呢?一个请求过来->打开Session->处理完业务->关闭Session,没问题啊而且所有页面均没有卡死的现像,难道代码里面有占用Session没关的地方。于是仔细分析代码终于被我发现问题了。我们的应用会定时启动几个quartz任务来处理复杂且影响页面响应时间的业务,这部分业务的业务数据是从数据库查的,只有业务数据全都被处理完后这个quartz才会结束。

因为Hibernate的Session是带有一级缓存的,每个经由Session查出来的对象会填充至一级缓存,以避免多次的数据库仿问。当这几个quartz任务的业务数据较多的时候,就会有很多对象被填入一级缓存这样一来持久化上下文中保存的对象越来越多。最终导致OOM.

 

【留给自己】

  • 大小: 70 KB
7
2
分享到:
评论
18 楼 xsh5324 2013-10-19  
libofeng 写道
会不会是没有实现hashCode, equals方法导致的?

我想应该不会是这没有实现这俩方法导致的(我们的应用中确实存在部分实体没有实现这两方法),据我了解 Hibernate中区分一个实体在不在一级缓存或持久化上下文中是通过EntityKey来区分的,而EntityKey是通过实体的ID和EntityModel创建的,EntityKey中实现了用于区分实体的equals和hashCode方法,所以 我们的实体中没有实现equals,hashCode应该不会导致加载重复实体到一级缓存中。

不知道我有没有误解您的意思?
17 楼 libofeng 2013-10-19  
会不会是没有实现hashCode, equals方法导致的?
16 楼 xsh5324 2013-10-18  
damoqiongqiu 写道
然后你是怎么解决的呢?亲?

哎哟,大漠兄 才注意到你的留言真不好意思啊。我们目前还只是简单在quartz调度的业务代码中加上session.clear(),虽然有点不体面但能解决问题。不知道大漠兄有什么更好的办法来解决???
15 楼 xsh5324 2013-10-18  
nello 写道
看完之后,没 Hibernate 一级缓存什么事情,自己代码写的有问题。

确实是我们的代码写得有问题,没有考虑到周全.
14 楼 xsh5324 2013-10-18  
qiaojoy99 写道
xsh5324 写道
求求你帮帮我 写道
怎么解决的啊

当处理完50个后手动调用session.clear();但是如果在session.clear()之前有做过update(),delete();save();操作,必需先session.flush();

这个数目是用什么来监视的?

这只是打个比方.具体视业务精况而定.
13 楼 wm5920 2013-10-18  
不错啊。。。。。
12 楼 qiaojoy99 2013-10-18  
xsh5324 写道
求求你帮帮我 写道
怎么解决的啊

当处理完50个后手动调用session.clear();但是如果在session.clear()之前有做过update(),delete();save();操作,必需先session.flush();

这个数目是用什么来监视的?
11 楼 nello 2013-10-18  
session.evict(obj);
10 楼 nello 2013-10-18  
看完之后,没 Hibernate 一级缓存什么事情,自己代码写的有问题。
9 楼 xsh5324 2013-10-18  
求求你帮帮我 写道
怎么解决的啊

当处理完50个后手动调用session.clear();但是如果在session.clear()之前有做过update(),delete();save();操作,必需先session.flush();
8 楼 fanzexi 2013-10-18  
damoqiongqiu 写道
然后你是怎么解决的呢?亲?

作者说了最后一句话:【留给自己】
7 楼 damoqiongqiu 2013-10-18  
然后你是怎么解决的呢?亲?
6 楼 defuxiaozhu_84 2013-10-18  
mark下,可能会遇到缓存的陷阱。
5 楼 求求你帮帮我 2013-10-18  
怎么解决的啊
4 楼 hui_windows 2013-10-18  
mark,在查询大量实体时,hibernate一级缓存确实会有OOM风险
session.clear()和session.evict(obj); 可以清楚一级缓存中的对象
3 楼 winhell 2013-10-18  
问题找出来了就好办了。
可以在quartz中释放对象的一级缓存
2 楼 rentianchou 2013-10-18  
解决方案??
1 楼 1426717012 2013-10-18  
只说了问题,没有看到解决方案

相关推荐

Global site tag (gtag.js) - Google Analytics