關於jvm的讀書筆記-oom定位

相信你們都有感觸,線上服務內存OOM的問題,是最難定位的問題,不過歸根結底,最多見的緣由:服務器

  • 自己資源不夠網絡

  • 申請的太多多線程

  • 資源耗盡架構

58到家架構部,運維部,58速運技術部聯合進行了一次線上服務內存OOM問題排查實戰演練,將內存OOM問題定位三板斧分享出來,但願對你們也有幫助。運維

題目ssh

某服務器上部署了Java服務一枚,出現了OutOfMemoryError,請問有多是什麼緣由,問題應該如何定位?socket

不妨設服務進程PID爲10765(沒錯,就是CPU佔用高的那個倒黴的進程《線上服務CPU100%問題快速定位實戰》)。工具

解決思路線程

Java服務OOM,最多見的緣由爲:3d

  • 有多是內存分配確實太小,而正常業務使用了大量內存

  • 某一個對象被頻繁申請,卻沒有釋放,內存不斷泄漏,致使內存耗盡

  • 某一個資源被頻繁申請,系統資源耗盡,例如:不斷建立線程,不斷髮起網絡鏈接


     

更具體的,能夠使用如下的一些工具逐一排查。

1、確認是否是內存自己就分配太小

方法:jmap -heap 10765

如上圖,能夠查看新生代,老生代堆內存的分配大小以及使用狀況,看是否自己分配太小。

 

2、找到最耗內存的對象

方法:jmap -histo:live 10765 | more

圖示

如上圖,輸入命令後,會以表格的形式顯示存活對象的信息,並按照所佔內存大小排序:

  • 實例數

  • 所佔內存大小

  • 類名

是否是很直觀?對於實例數較多,佔用內存大小較多的實例/類,相關的代碼就要針對性review了。

 

上圖中佔內存最多的對象是RingBufferLogEvent,共佔用內存18M,屬於正常使用範圍。

 

若是發現某類對象佔用內存很大(例如幾個G),極可能是類對象建立太多,且一直未釋放。例如:

  • 申請完資源後,未調用close()或dispose()釋放資源

  • 消費者消費速度慢(或中止消費了),而生產者不斷往隊列中投遞任務,致使隊列中任務累積過多

 

3、確認是不是資源耗盡

工具:

  • pstree

  • netstat

查看進程建立的線程數,以及網絡鏈接數,若是資源耗盡,也可能出現OOM。

 

這裏介紹另外一種方法,經過

  • /proc/${PID}/fd

  • /proc/${PID}/task

能夠分別查看句柄詳情和線程數。

 

例如,某一臺線上服務器的sshd進程PID是9339,查看

  • ll /proc/9339/fd

  • ll /proc/9339/task

如上圖,sshd共佔用了四個句柄

  • 0 -> 標準輸入

  • 1 -> 標準輸出

  • 2 -> 標準錯誤輸出

  • 3 -> socket(容易想到是監聽端口)

 

sshd只有一個主線程PID爲9339,並無多線程。

 

因此,只要

  • ll /proc/${PID}/fd | wc -l

  • ll /proc/${PID}/task | wc -l (效果等同pstree -p | wc -l)

就能知道進程打開的句柄數和線程數

相關文章
相關標籤/搜索