記一次記憶體溢位問題的排查、分析過程及解決思路

久曲健發表於2020-09-20

謹以此文獻給自學路上的兄弟

起因

這個測試工具的開發已有一段時間了,由於資料量過大,寫入資料較慢,導致工具執行耗時較長,所以再次優化了實現方案,進行二階段的程式開發。

經優化後,2000 條資料寫入,耗時4秒,個人感覺,快了很多了。

於是,想批量執行下,看下耗時多長。

結果10分鐘、20分鐘、1 個小時過去了...

程式一直在寫入資料,等的我這個藍瘦呀,尋思去泡杯茶吧。

結果,接完水回來,尼瑪報錯了,如下圖所示:

心裡過程

雖然,作為一個測試喵,編碼能力與純開發相比,根本不是一個層次的。

當然,也可以通過求助開發同事解決,但這並不是退縮、逃避解決問題的理由。

這個報錯,我也是第一次遇到,對於一個不瞭解記憶體問題的測試來說,無疑是艱難的,結果各種搜。

最後,定位到是記憶體溢位導致的。

說實話,這個報錯卡了我近1.5天,我幾次想找同事解決,但我還是忍住了,還是想嘗試自己去解決。

常見的幾種記憶體溢位

  • Java heap space
  • GC overhead limit exceeded
  • PermGen space
  • Metaspace

嘗試過程

小編經驗有限,目前只遇到過第1、2種記憶體溢位問題。

下面來分享下,我排查問題的思路及過程。

網上大多數的部落格和文章,寫的都是修改執行記憶體,我都試了一下,根本無效,廢棄方案如下:

 

 

黔驢技窮的我,突然想到之前效能測試,看到過開發通過JDK自帶工具jvisualvm,進行GC調優,結果還真的用上了。

如何操作

找到JDK安裝目錄 bin 下的 jvisualvm.exe,雙擊開啟,如下圖所示。

執行你要監控的程式,雙擊左側執行程式,工具中會顯示程式的執行情況,只保留記憶體,其他不選,如下圖所示。

記憶體溢位,所以我們暫時只關注記憶體就可以了,記憶體會顯示執行時堆內資料的變化,如物件例項等。

接著是內心等待,檢視監控記憶體情況,結果看到最大記憶體瞬間增長好幾倍,如下圖所示。

最大記憶體瞬間暴漲好幾倍,而且程式同時丟擲如下異常。

問題定位出來了,接下來就是復現查詢問題了。

將執行引數調整-Xmx216m,再次執行程式,同步驟 1、2,點選,堆 dump, 進入監控介面,點選切換至類選項卡如下圖所示。

結果終於被我找到這小子了,原來是它搞的鬼,建立了9314個char陣列物件。

雙擊這個類名,找到問題如下圖所。

找到問題後,接下來就是優化程式的事了。

解決方案

經過以上的排查,找到了問題的原因,是因為寫資料時超過允許最大行數導致的溢位,最後採取分段寫入,完美解決了這個問題。

雖然解決了記憶體溢位問題,但程式的執行依然很慢,後來又找到了大資料的寫入資料方法,經過程式的再次優化,260W資料全部寫完僅需54秒,真的是 VERY NICE!

以上就是我排查問題的整個過程,當然這個案例的程式碼是為了模擬記憶體溢位寫的一段程式,非業務程式碼,僅供參考的入門案例。

寫在最後

jvisualvm、 jprofile 真的是一個記憶體優化、排查問題的一個好工具,可以說是寫程式必備神器。

關於記憶體溢位問題的文章很多,對我而言,能用上的真的是少之又少,作為一個測試喵並不敢造次和評價,有興趣的同學可以去買本書去深入學習瞭解。

這裡要特別感謝強哥的幫助,每次都能給我很多的思路和靈感,讓我受益良多。

強哥

之前北京同事,多年經驗高階JAVA開發工程師

參考文章

解決專案中java heap space的問題[1]

記一次解決OutOfMemoryError: Java heap space詳細過程與解決思路[2]

參考資料

[1]   解決專案中java heap space的問題: https://blog.csdn.net/smh0310/article/details/90664598

[2]   記一次解決OutOfMemoryError: Java heap space詳細過程與解決思路: https://blog.csdn.net/lyflyyvip/article/details/82288719

相關文章