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


title: Hibernate 一级缓存导致某保险公司核心系统Weblogic中间件内存溢出的故障诊断
author: rocklei123
date: 2018-09-02 22:15:45
tags: [Hibernate, 缓存,内存溢出,WebLogic]
categories: Hibernate

1.客户环境

  • Weblogic版本:9.2
  • Linux :suse 12
  • JDK版本: Sun JDK 1.5

2.故障现象

在 201X 年 X 月 X 日早上 10 点多时,某保险公司核心系统多个
Weblogic 的应用服务器都极度缓慢,正常的业务都无法开展。

3.详细分析

应用缓慢原因

检查 Weblogic 的相关日志文件,发现有内存溢出的情况发生,如下:
java.lang.OutOfMemoryError: Java heap space

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

在这里插入图片描述

其中占据内存较多的两组对象都是产生了 Stuck 的 Weblogic 线程,分别占用的内存是 84.85%和 10.40%,这两部分加起来是 95.25%,

说明已经占用了整个 Weblogic Server 的绝大部分内存。

进一步分析内存溢出对象

进一步分析,发现大量的对象都被缓存在
(org.hibernate.engine.StatefulPersistenceContext)中.
在这里插入图片描述

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

在这里插入图片描述

业务对象如下:

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

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

StatefulPersistenceContext 解密

SessionImpl

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

161   	private transient ActionQueue actionQueue;
162   	private transient StatefulPersistenceContext persistenceContext;

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

persistenceContext缓存存储方式

当执行完以下这句代码:

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

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

在这里插入图片描述

在这里插入图片描述

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源码

[StatefulPersistenceContext源码](http://www.docjar.com/html/api/org/hibernate/engine/StatefulPersistenceContext.java.html "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    */

4.建议

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

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

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

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

关于Hibernate缓存问题可参考:
Hibernate缓存策略

5.可能场景

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

6.参考

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

7.了解Hibernate缓存策略请看

Hibernate缓存策略

Hibernate缓存策略

8.欢迎关注米宝窝,持续更新中,谢谢!

米宝窝 https://rocklei123.github.io/

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值