1. 背景
線上內存OOM問題是最難定位的問題,最常見的原因:
(1)本身資源不夠
(2)申請的太多
(3)資源耗盡
某服務器上部署了Java服務,出現OutOfMemoryError,請問有可能是什么原因,問題應該如何定位?
解決思路:
Java服務OOM,最常見的原因為:
(1)有可能是內存分配確實過小,而正常業務需要使用更大的內存;
(2)某一個對象被頻繁申請,卻沒有釋放,內存不斷泄露,導致內存耗盡;
(3)某一個資源被不斷申請,系統資源耗盡,例如:不斷創建線程,不斷發起網絡連接
2. 排查過程
2.1 確認是不是內存本身就分配過小
jmap -heap pid
如圖,可以查看新生代,老年代堆內存的分配大小以及使用情況,看是否本身分配過小。
2.2 找到最耗內存的對象
jmap -histo:live pid | more
如圖,結果以表格的形式顯示存活對象的信息,並按照所占內存大小排序:
實例數,所占內存大小,類名
如果發現某類對象占用內存很大,很可能是類對象創建太多,且一直未釋放。例如:
(1)申請完資源后,未調用close釋放資源
(2)消費者消費速度慢,生產者不斷往隊列中投遞任務,導致隊列中任務累積過多
2.3 確認釋放是資源耗盡
pstree:查看進程創建的線程數
netstat:網絡連接數
還有另一種方法,通過
ll /proc/pid/fd 查看占用句柄
ll /proc/pid/task 查看線程數
例如,某一台顯示服務器的sshd進程是1041,查看:
sshd共占用了5個句柄。
sshd只有一個主線程為1041,並沒有多線程。