天天看點

idea分析dump檔案_生産環境JVM記憶體溢出案例分析!

點選上方藍字 設為星标

idea分析dump檔案_生産環境JVM記憶體溢出案例分析!
每天傍晚18:00一起成長!
           
idea分析dump檔案_生産環境JVM記憶體溢出案例分析!

來源:blog.csdn.net/prestigeding/article/details/89075661

  • 分析思路:
    • 如何快速恢複業務
    • 分析解決問題
    • 收集記憶體溢出Dump檔案
    • 分析Dump檔案

如果我們所在公司的業務量比較大,在生産環境經常會出現JVM記憶體溢出的現象,那我們該如何快速響應,快速定位,快速恢複問題呢?

本文将通過一個線上環境JVM記憶體溢出的案例向大家介紹一下處理思路與分析方法。

案例:架構組接到某項目組回報,Zabbix監控上顯示JMX不可用,請求協助處理。

分析思路:

  • JMX不可用,往往是由于垃圾回收時間停頓時間過長、記憶體溢出等問題引起的。
  • 線上故障分析的原則是首先要采取措施快速恢複故障對業務的影響,然後才是采集資訊、分析定位問題,并最終給出解決辦法。

具體分析過程如下。

1

快速恢複業務

通常線上的故障會對業務造成重大影響,影響使用者體驗,故如果線上伺服器出現故障,應規避對業務造成影響,但不能簡單的重新開機伺服器,因為需要盡可能保留現場,為後續的問題分析打下基礎。

那我們如何快速規避對業務的影響,并能保留現場呢?

通常的做法是隔離故障伺服器。

通常線上伺服器是叢集部署,一個好的分布式負載方案會自動剔除故障的機器,進而實作高可用架構,但如果未被剔除,則需要運維人員将故障伺服器進行剔除,保留現場進行分析。

發生記憶體洩露,通常情況下是由于代碼的原因造成的,一般無法立即對代碼進行修複,很容易會發送連鎖反應造成應用伺服器一台一台接連當機,故障面積會慢慢擴大,針對此種情況,應快速定位發生記憶體洩露的原因,将該服務進行降級,避免對其他服務造成影響。最簡單的降級方法是根據F5(Nginx)轉發政策,對該功能定向到一個單獨的叢集,與其他流量進行隔離,確定其他業務不受牽連,給故障排查、解決提供寶貴的緩沖時間。

2

分析解決問題

首先可以通過檢視日志,确定是哪種記憶體溢出,堆記憶體溢出可發生的地方:Java heap space(堆空間)、perm space(持久代)。

idea分析dump檔案_生産環境JVM記憶體溢出案例分析!

收集記憶體溢出Dump檔案

收集Dump檔案有兩種方式:

  • 設定JVM啟動參數

    -XX:+HeapDumpOnOutOfMemoryError

    -XX:HeapDumpPath=/opt/jvmdump

在每次發生記憶體溢出時,JVM會自動将堆轉儲,dump檔案存放在-XX:HeapDumpPath指定的路徑下。

  • 使用jmap指令收集

    通過jmap -dump:live,format=b,file=/opt/jvm/dump.hprof pid。

分析Dump檔案

在擷取Dump檔案後,可以使用工具MAT(MemoryAnalyzer)進行分析,該工具大家可以通過百度自行下載下傳。

使用MAT打開Dump檔案後,首頁截圖如下:

idea分析dump檔案_生産環境JVM記憶體溢出案例分析!

工具按鈕介紹:

idea分析dump檔案_生産環境JVM記憶體溢出案例分析!

:直方圖視圖,将堆中所有的記憶體消耗情況統計出來,其如圖所示:

idea分析dump檔案_生産環境JVM記憶體溢出案例分析!
idea分析dump檔案_生産環境JVM記憶體溢出案例分析!

:記憶體使用樹狀結構,以線程為次元,樹狀形式展開,如圖所示:

idea分析dump檔案_生産環境JVM記憶體溢出案例分析!
idea分析dump檔案_生産環境JVM記憶體溢出案例分析!

線程棧,其截圖如下:

idea分析dump檔案_生産環境JVM記憶體溢出案例分析!
idea分析dump檔案_生産環境JVM記憶體溢出案例分析!

根據該圖,可以明确,堆的總大小為1.9G,被4個線程全部占據,導緻其他線程無法再申請資源,抛出堆記憶體溢出錯誤。

接下來,我通常的做法是直接去看

idea分析dump檔案_生産環境JVM記憶體溢出案例分析!

這個視圖(以線程為基本次元,查找線程中占用記憶體的對象),為後續定位排查提供必要的依據。

idea分析dump檔案_生産環境JVM記憶體溢出案例分析!
idea分析dump檔案_生産環境JVM記憶體溢出案例分析!

從上面的截圖中可以得出如下關鍵資訊點:

  • org.apache.ibatis.executor.result.DefaultResultHandler内部持有一個List,其原始為java.util.HashMap,從這個類基本可以看出是與資料庫的查詢相關,對資料庫傳回結果的解碼并組織成HashMap。
  • 這個List中的元素總共有146033個,初步可以判斷出是在一次查詢中從資料庫中一次查詢出了太多資料,造成了記憶體溢出。

由于SQL查詢代碼中,是用HashMap來接收資料庫中的傳回字段,無法一時間看出是那個查詢,那我們能不能精确找到是哪一個查詢,哪一行代碼,甚至與哪一條SQL語句呢?

答案是可以的,我們可以從

idea分析dump檔案_生産環境JVM記憶體溢出案例分析!

視圖一探究竟。

溫馨提示:
idea分析dump檔案_生産環境JVM記憶體溢出案例分析!
視圖使用技巧:展開技巧:沿着使用率最高的項一層一層進行展開,直至發現具體占用記憶體的對象。

接下來我們從 視圖去尋找是哪個方法,哪條SQL語句觸發的。

具體方法:首先完全展開一個線程,從展開圖的底部向上尋找:

其線程的入口(控制層代碼)

idea分析dump檔案_生産環境JVM記憶體溢出案例分析!

繼續往上查找,要找到SQL語句,應該找到Mybatis處理結果集相關的類,如圖所示:

idea分析dump檔案_生産環境JVM記憶體溢出案例分析!

然後展開boundSql即能找到SQL語句:

idea分析dump檔案_生産環境JVM記憶體溢出案例分析!

然後滑鼠可以放在SQL屬性中,右鍵,可以将SQL語句複制出來。

idea分析dump檔案_生産環境JVM記憶體溢出案例分析!

由于這裡涉及到公司的代碼機密,故在這裡不貼出具體的SQL語句。

這裡根據後面的分析,原來是在做導出功能的時候,沒有使用分頁對資料進行分頁查詢,分頁寫入Excel檔案,而是一次将全部資料查詢,導緻導出功能如果并發數超過4個時,就會将所有記憶體耗盡。

解決方案:

  • 首先在運維層面将該請求導入到指定的一台伺服器上,是導出任務與其他任務進行隔離,避免對其他重要服務造成影響。
  • 項目組對其代碼進行修複,可以使用分頁查資料,然後配置設定寫入Excel。

往期好文合集

圖解 SQL,這也太形象了吧!

14個Spring MVC頂級技巧,随時用随時爽,一直用一直爽~

這樣配置,讓你的 IDEA 好用到飛起來!

關注快哥,快學Java!
           
idea分析dump檔案_生産環境JVM記憶體溢出案例分析!

繼續閱讀