新闻中心
近年来,我们专注于提供企业级客户的数字化转型赋能/服务,以数据库/中间件运维咨询服务、数据库国产化改造服务、开源数据库技术栈服务、数据中心硬件带外监控服务、大数据服务、AI开发平台为核心业务,是IT智能运维服务提供商。
返回列表
首页 / 新闻资讯 / 行业资讯
案例 | 核心系统中间件Hibernate一级缓存导致内存溢出的故障诊断
来源:周磊 东方龙马(OLM)· 北京   日期:2019-04-12



一、客户环境


o Weblogic版本:9.2

o Linux :suse 12

o JDK版本: Sun JDK 1.5





二、故障现象



某保险公司核心系统多个Weblogic 的应用服务器都极度缓慢,正常的业务都无法开展。




三、详细分析


     应用缓慢原因



检查 Weblogic 的相关日志文件,发现有内存溢出的情况发生,如下:

java.lang.OutOfMemoryError: Java heap space


并产生了相关的内存溢出 HeapDump 文件:java_pid25528.hprof 随后对该文件进行下一步分析,可知:


某保险公司核心系统中间件Hibernate 一级缓存导致内存溢出的故障诊断1847.png


其中占据内存较多的两组对象都是产生了 Stuck 的 Weblogic 线程,分别占用的内存是 84.85%和 10.40%,这两部分加起来是 95.25%,说明已经占用了整个 Weblogic Server 的绝大部分内存。



     进一步分析内存溢出对象



进一步分析,发现大量的对象都被缓存在(org.hibernate.engine.StatefulPersistenceContext)中。


某保险公司核心系统中间件Hibernate 一级缓存导致内存溢出的故障诊断2480.png


在这个缓存中的 对 象 是我们的业务对象


某保险公司核心系统中间件Hibernate 一级缓存导致内存溢出的故障诊断2503.png


业务对象如下:


com.**.scms.inf.model.ScmsCcommission

com.**.scms.inf.model.ScmsCcomissionId



由于这些缓存的数据无法释放,系统在业务量较大时,内存迅速 在 2 分钟内从 1G 增长到 4G,并且不断地进行 Full GC,导致系统极其缓慢。



     StatefulPersistenceContext 解密



SessionImpl

Hibernate的一级缓存就是指Session缓存。通过查看Session接口的实现类——SessionImpl.java的源码可发现有如下两个类:



private transient ActionQueue actionQueue;

private transient StatefulPersistenceContext persistenceContext;



actionQueue它是一个行动队列,它主要记录crud操作的相关信息。persistenceContext它是持久化上下文,它其实才是真正的缓存。



     persistenceContext缓存存储方式



当执行完以下这句代码:


Customer customer = session.get(Customer.class, 1);



就会向一级缓存中存储数据,一级缓存其底层使用了一个Map集合来存储,Map的key存储的是一级缓存对象,而value存储的是快照。通过在这句代码上打个断点,然后以debug的方式运行,Watch一下session会看得更加清楚,如下:

 

某保险公司核心系统中间件Hibernate 一级缓存导致内存溢出的故障诊断4362.png

某保险公司核心系统中间件Hibernate 一级缓存导致内存溢出的故障诊断4364.png

 


     Hibernate session的清理方法



从如下的代码中,也可以看出,session在执行相关清理工作时,也会执行persistenceContext.clear();



public void clear() {

  281   errorIfClosed();

  282   checkTransactionSynchStatus();

  283   persistenceContext.clear();

  284   actionQueue.clear();

  285   }

  466   /**

  467    * clear all the internal collections, just

  468    * to help the garbage collector, does not

  469    * clear anything that is needed during the

  470    * afterTransactionCompletion() phase

  471    */

  472   private void cleanup() {

  473   persistenceContext.clear();

  474   }


     StatefulPersistenceContext源码


org.hibernate.engine.StatefulPersistenceContext结合以上代码和该类的实现类可以确定是一个缓存上下文引用,而且从session.cleanup()方法session.cleanup()实际调用的就是persistenceContext.clear(),注意这句话clear all the internal collections, just to help the garbage collector; 




/**

58   import org.hibernate.util.IdentityMap;

59   import org.hibernate.util.MarkerObject;

62    * A <tt>PersistenceContext</tt> represents the state of persistent "stuff" which

63    * Hibernate is tracking.  This includes persistent entities, collections,

64    * as well as proxies generated.

65    * </p>

66    * There is meant to be a one-to-one correspondence between a SessionImpl and

67    * a PersistentContext.  The SessionImpl uses the PersistentContext to track

68    * the current state of its context.  Event-listeners then use the

69    * PersistentContext to drive their processing.

70    *

71    * @author Steve Ebersole

72    */



四、建议



由于 Hibernate 的一级缓存是其内部使用的,无法关闭或停用(随着Session 销毁)。从Hibernate 的手册或文档中可知,Hibernate 的一级缓存的清除可通过以下方式:


1)对于单个对象的清除:

Session session=sessionFactory.getCurrentSession(); session.evict(entity);


2)对于实体集合的清除:

Session session=sessionFactory.getCurrentSession(); session.clear();建议在程序中加入对 Hibernate 一级缓存的清除工作,以便可以其内存数据可以及时释放。




五、可能场景



如果应用会定时启动几个quartz任务来处理复杂且影响页面、响应时间的业务,这部分业务的业务数据是从数据库查的,只有业务数据全都被处理完后这个quartz才会结束。当这几个 quartz任务的业务数据较多的时候,就会有很多对象被填入一级缓存这样一来持久化上下文中保存的对象越来越多。最终导致OOM。




六、参考


http://www.docjar.com/html/api/org/hibernate/engine/StatefulPersistenceContext.java.html

http://www.docjar.com/html/api/org/hibernate/impl/SessionImpl.java.html

https://blog.csdn.net/yerenyuan_pku/article/details/70148567

https://www.cnblogs.com/hyl8218/p/5076338.html





七、了解Hibernate缓存策略请看


Hibernate缓存策略 https://rocklei123.github.io/categories/Hibernate/




|  北京    |    上海    |   广州    |   成都    |


4008-906-960



4008-906-960

全国免费咨询电话
  • 官方微博
  • 官方微信
Copyright 1998-2024 版权所有 北京东方龙马软件发展有限公司 京ICP备14000200号-1