記一次記憶體溢出問題的排查、分析過程及解決思路
- 2020 年 9 月 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的問題: //blog.csdn.net/smh0310/article/details/90664598
[2] 記一次解決OutOfMemoryError: Java heap space詳細過程與解決思路: //blog.csdn.net/lyflyyvip/article/details/82288719