天天看點

工作中一次記憶體溢出,查到到解決問題記載

由于公司資訊安全問題,一些檔案、照片無法取出,隻能口述一下

介紹一下問題背景:這是一個老項目,和信用卡相關的系統,每天淩晨會有多個定時任務啟動,把檔案裡的資料讀取出來,生成待辦任務,或者查詢資料庫相應的資料生成相應的代辦任務,等類似的任務推送給卡商(信用卡進行中心),每天的資料量大概幾萬,如果前幾天資料有擠壓,等服務通了以後就會有幾十萬或者更多的資料産生等待處理;

事發時間:國慶假期;

異常:記憶體溢出;

處理方式:重新開機伺服器後,服務正常使用;

後續跟進:一開始沒有當機檔案走了很多彎路走了很多彎路,沒有找到根本原因;隻知道某一行代碼那報錯導緻的記憶體溢出,但是那行代碼隻是查詢資料庫得到一個list,然後for循環list;資料量并不是很大,建立的對象并沒有被持續持有,不至于導緻記憶體溢出;

最初的解決辦法是一個不是辦法的辦法,去監聽服務如果服務挂了,或者沒有正确的往資料庫指定的某張表寫入資料,則停止服務,再拉起來;但是這個方法治标不治本;

後來拿到dump檔案,用IBM HEAPANALYZER 打開發現百分之99的記憶體都被用來存在MQreceiver對象,通過IBM HEAPANALYZER一層層檢視最後發現是XML中配置的transport類中(用來調用SOA上釋出的服務)建立的MQreceiver對象,我們通過debug斷點把整個調用流程走了一遍,并沒有發現什麼異常,後來在另一個項目中(同樣也用到SOA上的服務)也通過debug斷點把流程走了一遍,發現每次soa調用完成時,會調用MQreceiver類裡的close()方法,close方法中就會銷毀MQreceiver對象引用,等垃圾回收的時候就會把MQreceiver對象給回收掉,最終比對了一下MQreceiver對象那個jar包發現老項目中用到jar包版本是1.0版本,新項目用到的jar包是7.0以後的版本,由于1.0版本裡并沒有對MQreceiver對象的引用及時的銷毀,導緻如果過多的調用SOA服務時就會建立很多個MQreceiver對象,長時間的累積就是OutOfMemory,最後把低版本的和MQ相關的jar包全部換成高版本的MQ jar包問題得到了解決。

問題說的可能比較簡單但是實際上走了很多彎路沒有叙述,本文隻是記錄一下這一次遇到的bug,希望對以後有幫助,也希望對各位看官有所幫助,不喜勿噴,多多包涵

繼續閱讀