里昂酒店
新聞中心
近年來,我們專注于提供全系列企業級性能管理方案和相關的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。




六、參考


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

//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-2016 版權所有 北京東方龍馬軟件發展有限公司 京ICP備14000200號-1
捕鱼达人2修改 建斗牛的群怎么赚钱 冰晶科技怎么玩赚钱 玩探探怎么赚钱 创奇游戏怎么赚钱 海王捕鱼代充平台 淘宝怎么举报赚钱 在广州开滴滴赚钱 经纬彩票网址 淘宝联盟团长招商怎么赚钱 二手车做分期怎么赚钱 怎么玩打麻将 网上用手机浏览广告怎么赚钱 我秀怎么赚钱吗 无网单机麻将 捕鱼游戏画面