記一次生產(chǎn)內(nèi)存泄漏問(wèn)題

時(shí)間: 2018年3月16號(hào)晚

表現(xiàn)現(xiàn)象: 客戶訪問(wèn)非常慢到最后無(wú)法打開(kāi)

pinpoint請(qǐng)求: 請(qǐng)求逐步變慢(圖1),持續(xù)Full GC&CPU占用率高(圖2)暴匠,出現(xiàn)OOM(圖3

緊急措施: 加大內(nèi)存竭缝、重啟服務(wù)器
重現(xiàn)問(wèn)題: 測(cè)試環(huán)境模擬并發(fā)訪問(wèn)(10線程&10000次/線程)房维,開(kāi)jmx端口&Virtual VM監(jiān)控(圖4),問(wèn)題重現(xiàn)抬纸,啟動(dòng)兩三分鐘后開(kāi)始出現(xiàn)GC咙俩,后續(xù)內(nèi)存持續(xù)上漲,dump堆轉(zhuǎn)儲(chǔ)文件

分析問(wèn)題: MAT(Memory Analyzer tool)分析湿故,找泄露的代碼

  1. 從MAT的分析可以看出阿趁, javax.crypto.JceSecurity 的實(shí)例占用了最多的堆內(nèi)存(Retained Heap | 深堆) (圖5

  2. 從dominated tree可以看到,javax.crypto.JceSecurity 的實(shí)例的retained heap占了73% (圖6)坛猪,主要是一個(gè)IdentityHashMap類型的屬性verificationResults脖阵,放了很多org.bouncycastle.jce.provider.BouncyCastleProvider 對(duì)象, 每個(gè)的retained heap占用182712字節(jié) (圖7

  3. 另外從virtual vm看轉(zhuǎn)儲(chǔ)堆上的線程墅茉, 有很多BLOCKED的線程命黔, 都卡在javax.crypto.JceSecurity.getVerificationResult(JceSecurity.java:173)圖8),按現(xiàn)象看應(yīng)該是在等待Full GC

  4. 從getVerificationResult可以看出就斤, 只要新傳入Provider都會(huì)放到verificationResults緩存起來(lái)悍募,
    看調(diào)用鏈上(Rsa的decrypt 圖11-> Cipher.getInstance 圖12 -> JceSecurity.getVerificationResult 圖13),Rsa的解密不應(yīng)該每次重新new org.bouncycastle.jce.provider.BouncyCastleProvider 對(duì)象战转。

  5. BouncyCastleProvider的問(wèn)題(圖12搜立、13):

a. provider自己是一個(gè)java.util.Properties,將所有的預(yù)設(shè)的provider的key槐秧, value都作為property put到自己的hashtable里啄踊;

b. 如果key, value都是string的話, 還將他們放到一個(gè)java.util.LinkedHashMap.LinkedHashMap<String,String>() 的屬性 legacyStrings里刁标;

c. 在java.security.Provider.getService(String, String) 的時(shí)候颠通, 會(huì)把legacyStrings里所有的key,value解析成ServiceKey,Service對(duì),放到另一個(gè)java.util.LinkedHashMap.LinkedHashMap<ServiceKey,Service>() 的屬性legacyMap里

d. 因此膀懈,每次new BouncyCastleProvider 都會(huì)產(chǎn)生非常多的對(duì)象和引用(占用182712字節(jié))顿锰,且緩存在JceSecurity的verificationResults沒(méi)法釋放。

解決問(wèn)題: 按照BouncyCastleProvider 的注釋启搂,改代碼硼控,將BouncyCastleProvider實(shí)例對(duì)象作為Rsa的靜態(tài)成員變量可以解決問(wèn)題。

驗(yàn)證上線: 更改后再驗(yàn)證(圖14)胳赌,內(nèi)存使用正常牢撼,CPU正常

備 注: 其實(shí), 在重現(xiàn)問(wèn)題疑苫,設(shè)置jmx端口熏版,用jmeter測(cè)試的時(shí)候,已經(jīng)開(kāi)始在看代碼捍掺, 因?yàn)樽罱泳椭患恿私饷艿拇a撼短,除了Cipher.getInstance("RSA", new org.bouncycastle.jce.provider.BouncyCastleProvider()); 這句,其他地方看不出來(lái)會(huì)出現(xiàn)內(nèi)存泄露挺勿,于是曲横,順著看下去,就看到javax.crypto.JceSecurity.getVerificationResult 里的緩存不瓶,回頭看了下BouncyCastleProvider就確定懷疑正確禾嫉。 然后緊急版本線上了再說(shuō)。virtual vm和MAT的截圖都是后續(xù)再分析時(shí)候截的湃番。

<span id="圖1">圖1</span>


response_from_pinpoint
response_from_pinpoint

<span id="圖2">圖2</span>


full_gc_oom
full_gc_oom

<span id="圖3">圖3</span>


oom_of_pinpoint_trace
oom_of_pinpoint_trace

<span id="圖4">圖4</span>


monitor_by_virtualvm
monitor_by_virtualvm

<span id="圖5">圖5</span>


mat_analyze_summary
mat_analyze_summary

<span id="圖6">圖6</span>


mat_dominator_tree
mat_dominator_tree

<span id="圖7">圖7</span>


mat_list_objects_of_jcesecurity
mat_list_objects_of_jcesecurity

<span id="圖8">圖8</span>


virtualvm_thread_blocked
virtualvm_thread_blocked

<span id="圖9">圖9</span>


jcesecurity_getverifycationresult
jcesecurity_getverifycationresult

<span id="圖10">圖10</span>


cipher_getinstance
cipher_getinstance

<span id="圖11">圖11</span>


bad_code
bad_code

<span id="圖12">圖12</span>


bouncycastleprovilder
bouncycastleprovilder

<span id="圖13">圖13</span>


jcesecurity_three_map
jcesecurity_three_map

<span id="圖14">圖14</span>


solve_the_problem
solve_the_problem
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末夭织,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子吠撮,更是在濱河造成了極大的恐慌尊惰,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,482評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件泥兰,死亡現(xiàn)場(chǎng)離奇詭異弄屡,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)鞋诗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門膀捷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人削彬,你說(shuō)我怎么就攤上這事全庸⌒阒伲” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,762評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵壶笼,是天一觀的道長(zhǎng)神僵。 經(jīng)常有香客問(wèn)我,道長(zhǎng)覆劈,這世上最難降的妖魔是什么保礼? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,273評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮责语,結(jié)果婚禮上炮障,老公的妹妹穿的比我還像新娘。我一直安慰自己坤候,他們只是感情好胁赢,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評(píng)論 5 373
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著铐拐,像睡著了一般徘键。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上遍蟋,一...
    開(kāi)封第一講書(shū)人閱讀 49,046評(píng)論 1 285
  • 那天吹害,我揣著相機(jī)與錄音,去河邊找鬼虚青。 笑死它呀,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的棒厘。 我是一名探鬼主播纵穿,決...
    沈念sama閱讀 38,351評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼奢人!你這毒婦竟也來(lái)了谓媒?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 36,988評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤何乎,失蹤者是張志新(化名)和其女友劉穎句惯,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體支救,經(jīng)...
    沈念sama閱讀 43,476評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡抢野,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評(píng)論 2 324
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了各墨。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片指孤。...
    茶點(diǎn)故事閱讀 38,064評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖贬堵,靈堂內(nèi)的尸體忽然破棺而出恃轩,到底是詐尸還是另有隱情结洼,我是刑警寧澤,帶...
    沈念sama閱讀 33,712評(píng)論 4 323
  • 正文 年R本政府宣布详恼,位于F島的核電站补君,受9級(jí)特大地震影響引几,放射性物質(zhì)發(fā)生泄漏昧互。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評(píng)論 3 307
  • 文/蒙蒙 一伟桅、第九天 我趴在偏房一處隱蔽的房頂上張望敞掘。 院中可真熱鬧,春花似錦楣铁、人聲如沸玖雁。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,264評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)赫冬。三九已至,卻和暖如春溃列,著一層夾襖步出監(jiān)牢的瞬間劲厌,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,486評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工听隐, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留补鼻,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,511評(píng)論 2 354
  • 正文 我出身青樓雅任,卻偏偏與公主長(zhǎng)得像风范,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子沪么,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容