根據堆疊日誌定位記憶體洩漏

2022-08-30 22:18:26 字數 1482 閱讀 7774

【問題描述】:服務後端是3節點集群,凌晨出現2節點磁碟打滿告警並導致業務中斷,定位發現是jvm堆疊日誌hprof,該檔案比較大(大概10g+)。恢復線上業務後,剛好另一節點磁碟沒有滿,並打出堆疊日誌,可以用來定位此次故障原因。

工具:memoryanalyzer-1.8.1.20180910-win32.win32.x86_64

tomcat bin/setenv.sh配置堆疊日誌:

export catalina_opts="$catalina_opts -xx:+heapdumponoutofmemoryerror"

export catalina_opts="$catalina_opts -xx:heapdumppath=/opt/admin/logs/cloudnetmonitor-computer"

【定位過程】:

第一步 從線上匯出堆疊日誌到本地分析

由於公司安全策略,線上與本地網路隔離,需要堡壘機傳送檔案並且限制大小,在linux伺服器上需要拆分日誌檔案:

拆包: tar czf - sourcefile | split -b 90m - dest_split.

合併:cat dest_split.* >> dest.tar.gz

解包:tar zxvf dest.tar.gz

第二步 啟動mat工具

啟動前配置memoryanalyzer檔案,調大記憶體 -xmx12g

mat工具 file- open head dump 匯入hprof檔案,大檔案可能持續一段時間,匯入後

第三步 分析記憶體洩漏

mat工具提供的分析還是比較全面,檢視「accumulated objects in dominator tree」,發現是執行緒池佇列長度打滿,而且該佇列是個鍊錶阻塞佇列,轉到對應**位置

問題**位置:

private executorservice fixedthreadpool = executors.newfixedthreadpool(10);

檢視固定執行緒池原始碼:

找到問題了,這裡預設定義的是不指定容量大小的阻塞佇列,意味著是無限大小。作為開發者,我們需要注意的是,如果構造乙個linkedblockingqueue物件,而沒有指定其容量大小,linkedblockingqueue會預設乙個類似無限大小的容量(integer.max_value),這樣的話,如果生產者的速度一旦大於消費者的速度,也許還沒有等到佇列滿阻塞產生,系統記憶體就有可能已被消耗殆盡了。

C 記憶體洩漏定位 valgrind

new 和 delete 不匹配導致記憶體洩漏。最開始因為指標被我不小心delete了,導致有錯誤,就遮蔽了。網上學習了用valgrind 定位洩漏記憶體的位置,比較方便。然後,編譯源程式,比如 g g o testexe testexe.cpp 然後利用valgrind 進行定位,可執行程式可能有...

定位一起記憶體洩漏

建立乙個自定義列表 如何建立乙個註腳 注釋也是必不可少的 katex數學公式 新的甘特圖功能,豐富你的文章 uml 圖表 flowchart流程圖 匯出與匯入 你好!這是你第一次使用markdown編輯器所展示的歡迎頁。如果你想學習如何使用markdown編輯器,可以仔細閱讀這篇文章,了解一下mar...

記憶體洩漏了,該如何定位

程序的使用者空間記憶體包括了多個不同的記憶體段,比如唯讀段 資料段 堆 棧 以及檔案對映等,這些記憶體段是應用程式使用記憶體的基本方式。比如再程式中定義乙個區域性變數,int data 64 就定義了乙個可以儲存64個整數的記憶體段,由於是區域性變數,會從記憶體空間的棧中分配。記憶體洩漏的危害非常大...