OOM排查與定位

某Java服務(假設PID=19813)出現了OOM,最常見的原因爲:
有可能是內存分配確實過小,而正常業務使用了大量內存
某一個對象被頻繁申請,卻沒有釋放,內存不斷泄漏,導致內存耗盡
某一個資源被頻繁申請,系統資源耗盡,例如:不斷創建線程,不斷髮起網絡連接
三種情況:

1 “本身資源不夠”

2 “申請資源太多”

3: “資源耗盡”。
 更具體的,可以使用以下工具逐一排查。

jps列出所有java進程

一、確認是不是內存本身就分配過小
jmap -heap 19813


如上圖,可以查看新生代,老生代堆內存的分配大小以及使用情況,看是否本身分配過小。

二、找到最耗內存的對象
方法:jmap -histo:live 19813  |  more

如上圖,輸入命令後,會以表格的形式顯示存活對象的信息,並按照所佔內存大小排序:
實例數
所佔內存大小
類名
是不是很直觀?對於實例數較多,佔用內存大小較多的實例/類,相關的代碼就要針對性review了。
上圖中佔內存最多的對象是char 類型 ,共佔用內存11M,屬於正常使用範圍。

 1:         79988       11142328  [C


如果發現某類對象佔用內存很大(例如幾個G),很可能是類對象創建太多,且一直未釋放。例如:
申請完資源後,未調用close()或dispose()釋放資源
消費者消費速度慢(或停止消費了),而生產者不斷往隊列中投遞任務,導致隊列中任務累積過多
畫外音:線上執行該命令會強制執行一次fgc。另外還可以dump內存進行分析。


三、確認是否是資源耗盡工具:
pstree
netstat
查看進程創建的線程數,以及網絡連接數,如果資源耗盡,也可能出現OOM。 這裏介紹另一種方法,通過
/proc/${PID}/fd
/proc/${PID}/task
可以分別查看句柄詳情和線程數。 例如,某一臺線上服務器的sshd進程PID是19813,查看
ll /proc/19813/fd
ll /proc/19813/task

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章