記一次OOM問題排查過程

這周生產環境出了久違的java.lang.OutOfMemoryError: Java heap space,花了些時間找了下緣由,記錄分享一下 🥕java

OOM分析

以前的jvm優化的文章中,有提到要增長-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/data/logs/login/gc,這對於排查問題很是有幫助,當發生OOM時就會輸出堆的內存快照(hprof文件)。git

從生產環境拷貝出hprof文件後,就能夠用MAT或者Jvisualvm來分析了,相對來講MAT更智能和易用一些。github

用MAT打開hprof文件後,很明顯能夠看到(這裏補充一個小插曲:在jdk11的環境下,MAT會報錯沒法打開,建議切回jdk8的環境打開MAT)spring

經過Leak Suspects其實已經能夠看出問題所在了,SessionFactoryImpl這個實例佔用了87.48%的內存。很明顯是內存泄漏了。sql

MAT-1

咱們打開Histogram,能夠看到類的實例數和所佔的內存緩存

MAT-1

這個看起來還並非很清晰,能夠排除軟,弱,虛引用(剩下強引用)看的更加直觀bash

MAT-1

如今就很明顯了,SessionFactoryImpl中的QueryPlanCache形成了內存泄漏jvm

MAT-1

QueryPlanCache內存泄漏解決

那什麼是QueryPlanCache呢,hibernate中的QueryPlanCache會緩存sql,以便於後邊的相同的sql重複編譯。優化

若是in後的參數不一樣,hibernate會把其當成不一樣的sql進行緩存,從而緩存大量的sql致使heap內存溢出。spa

因此能夠經過設置緩存最大值來進行限制,不設置默認是2G。

spring:
  jpa:
    properties:
      hibernate:
        query:
          plan_cache_max_size: 64
          plan_parameter_metadata_max_size: 32
複製代碼

Github 不要吝嗇你的star ^.^
更多精彩 戳我

相關文章
相關標籤/搜索