世界即時(shí):問題解決系列:記錄一次Java程序內(nèi)存泄露的解決過程(proxool內(nèi)存泄露)

2022-12-07 18:25:04 來源:51CTO博客

一、問題場景

在線上運(yùn)行的程序,有一天突然前端響應(yīng)緩慢,但是后臺日志依舊還在正常輸出。針對這種情況,本篇博客主要是進(jìn)行問題解決的過程說明。

二、問題環(huán)境

軟件

版本


(資料圖片僅供參考)

Centos

6.4

JDK

1.6

proxool

0.9.0RC3

三、問題原因

1. 使用top命令查看進(jìn)程情況

2. 使用jstat命令查看當(dāng)前GC情況

jstat -gcutil  13062 5000

從上圖可以看出,現(xiàn)在項(xiàng)目是處于頻繁GC的狀態(tài),內(nèi)存基本都被占滿了。

3. 使用jmap命令打印當(dāng)前存活的最大20個(gè)對象

jmap -histo:live 13062 | head -20

從上圖可以看到,目前是數(shù)據(jù)庫相關(guān)的類占用了比較大的空間。其中有proxool,這個(gè)時(shí)候猜測是因?yàn)閜roxool的問題導(dǎo)致的。

4. 使用jmap保存當(dāng)前堆棧信息

jmap -dump:format=b,file=heap-dump.bin 13062

5. 使用MAT工具進(jìn)行head.dump的分析

將第4步導(dǎo)出的堆棧信息,使用MAT工具打開,打開之后,進(jìn)行分析,分析結(jié)果如下:

從圖中,可以知道,F(xiàn)inalizer占用了最大的空間,達(dá)到了2.9GB。

6. 使用jstack命令獲取進(jìn)程的堆棧信息

之后,我們使用以下命令將該進(jìn)程的堆棧信息dump下來,如下:

jstack 13062 > 13062 _error.log

并搜索Finalizer字眼,結(jié)果如下:

7. 鎖定問題

這個(gè)就是比較著名的??proxool???內(nèi)存泄露問題,在??JVM???回收??WrappedConnection???對象時(shí),由于代理類重寫了??finalize???方法,??WrappedConnection???方法被丟進(jìn)引用隊(duì)列等待??finalizer???線程執(zhí)行??finalize???方法,??finalize???本身沒有額外的實(shí)現(xiàn),但是代理類在執(zhí)行該方法之前會做一個(gè)??isClose???的判斷,而??jdbc oracle???的實(shí)現(xiàn)類則使用了??synchronize???修飾了??isClose???,導(dǎo)致業(yè)務(wù)邏輯從池里拿出來該連接使用的時(shí)候會與??finalize???線程競爭該鎖,一旦業(yè)務(wù)邏輯處于繁忙狀態(tài)則??finalizer??線程執(zhí)行的頻率大大減小,此時(shí)在隊(duì)列中的引用依然存在,對象仍然會在堆中存活。

四、解決方案

既然知道了原因,那么覆寫??org.logicalcobwebs.proxool.WrappedConnection??類,添加以下代碼:

然后重新編譯提交到項(xiàng)目中,并重啟。

五、結(jié)果

升級補(bǔ)丁之后,重啟項(xiàng)目。到了第二天,再將堆棧信息dump下來查看,已經(jīng)沒有Finalizer的內(nèi)存占用了。問題得到解決。

六、總結(jié)

本篇博文主要是記錄此次解決過程中使用的各種命令,熟悉使用可以解決很多問題。

七參考鏈接

??解決proxool連接oracle內(nèi)存溢出的問題????壓測調(diào)優(yōu)之遇到的proxool問題??

隨緣求贊

如果我的文章對大家產(chǎn)生了幫忙,可以在文章底部點(diǎn)個(gè)贊或者收藏;如果有好的討論,可以留言;

如果想繼續(xù)查看我以后的文章,可以點(diǎn)擊關(guān)注可以掃描以下二維碼,關(guān)注我的公眾號:楓夜之求索閣,查看我最新的分享!

標(biāo)簽: 問題解決 分析結(jié)果 升級補(bǔ)丁

上一篇:全球滾動:Shell中色彩處理
下一篇:全球即時(shí)看!#yyds干貨盤點(diǎn)# 名企真題專題:最大差值