記一次現(xiàn)網(wǎng)內存泄漏問題排查和分析
本文轉載自微信公眾號「愛笑的架構師」,作者雷小帥。轉載本文請聯(lián)系愛笑的架構師公眾號。
大家好,我是雷小帥!大家春節(jié)過得咋樣,反正我是挺崩潰的。本來給自己列了好多計劃,最終的執(zhí)行效果是這樣的:
- 寫幾篇技術文章
- 看幾本技術書籍
爽快玩了幾天,走親戚,看電影
哈哈,既然過年沒好好學習,那只有熬夜趕作業(yè)了。
今天這篇文章帶大家分析一個內存異常的問題,也算是新年的第一篇技術文章了,開工大吉~~~
我們有個新服務上線運行一段時間后,老是出現(xiàn)堆內存不足,大量出現(xiàn) Full GC,有些實例甚至出現(xiàn)內存溢出錯誤:
java.lang.OutOfMemoryError: Java heap space
但是為什么會內存溢出呢?按說訪問量也不是很高,于是進行了下面的排查和分析。
1、懷疑內存泄漏
進入 APM 監(jiān)控系統(tǒng)查看實例內存情況,把時間線拉長到一天,可以看到內存有緩慢上升趨勢,初步懷疑有內存泄漏。
2、Heap Dump
獲取到機器ip,聯(lián)系運維人員去機器上把堆dump下來,dump命令:
/xxx/jdk1.8.0_212/bin/jmap -dump:live,format=b,file=/xxx/xxx.hprof 進程號
將堆dump文件 Xxx.hprof 下載到本地。
3、下載Heap Dump分析工具
常用的分析工具有MAT和JProfile,本文以MAT工具為示例進行分析。工具下載鏈接如下:
??https://www.eclipse.org/mat/downloads.php??
注意:如果你本地安裝的是JDK11+,下載最新的即可;如果你本地安裝的是JDK8,建議下載1.9.2版本。
4、將Dump文件導入MAT工具
MAT是eclipse的一個插件,免安裝,雙擊打開即可使用。
打開下載好的dump文件
5、分析Dump文件
打開內存泄漏懷疑分析報告,可以看到 SessionFactoryImpl 這個對象使用了 149M內存,占總內存的25%,這肯定不正常。
SessionFactoryImpl 這個類是跟數(shù)據(jù)庫相關,服務代碼中使用了JPA作為持久層框架,應該是跟JPA相關,繼續(xù)往下分析。
我們打開內存樹,往下挖,可以看到 QueryPlanCache 這個對象占用內存比較大。
QueryPlanCache 表面的意思是:查詢計劃緩存。用google查一下具體含義。
簡單來說Hibernate會緩存sql語句以減少重復編譯,便于直接命中提高效率。
在使用 SQL in 的時候,如果 in 后的參數(shù)不同,hibernate會把其當成不同的sql進行緩存,從而緩存大量的sql。
緩存的大小是多少?查了一下官方文檔,如果不配置,這個緩存默認最大值為2048 。
Stack Overflow上也有用戶反饋這個問題:
https://stackoverflow.com/questions/31557076/spring-hibernate-query-plan-cache-memory-usage
7、分析結論
drawio服務里面有大量的 sql in 語句,in 后面的參數(shù)不一樣造成Hibernate緩存了大量SQL語句,占用大量的堆內存。
8、解決措施
(1)添加配置參數(shù),限制緩存大小
參數(shù)解釋:
https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#configurations-query
(2)提高 sql in 的緩存效率
參數(shù)解釋:
https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#configurations-query