Hibernate內存溢出分析一例


 

公司業務系統在進行壓力測試時,壓測24小時后系統發生內存溢出。經過分析讀dump文件,發現org.hibernate.stat.StatisticsImpl類的hashmap類型的變量存儲了大量數據(3百多萬條),此成員變量消耗了2g的內存。如下圖:

    

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作為queryStatistics的key,此map的數量量過大說明查詢的sql或hql語句的查詢條件不是變量綁定或預編譯的寫法,在進行大量的動態sql、hql查詢時就會導致此問題。

 

從此次問題也說明以下兩點很重要:

  1. 在編寫sql、hql是應采用變量綁定或預編譯的寫法(如where id=?或where id=:id),避免出現大量不同的sql語句。如未遵循這個規則,在數據庫中也會發生比較高的硬簡析。
  2. hibernate.generate_statistics的功能在生產環境應禁用。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM