日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
又抓了一個(gè)導(dǎo)致頻繁GC的鬼--數(shù)組動(dòng)態(tài)擴(kuò)容

概述

本周有個(gè)同事過(guò)來(lái)咨詢一個(gè)比較詭異的gc問(wèn)題,大概現(xiàn)象是,系統(tǒng)一直在做cms gc,但是老生代一直不降下去,但是執(zhí)行一次jmap -histo:live之后,也就是主動(dòng)觸發(fā)一次full gc之后,通過(guò)jstat -gcutil來(lái)看老生代一下就降下去了,初看下理論上不太可能,因?yàn)閒ull gc也會(huì)對(duì)old做回收,于是我要同事針對(duì)他們的場(chǎng)景寫了一個(gè)簡(jiǎn)單的demo出來(lái),然后果然還真能重現(xiàn),不過(guò)他的demo設(shè)置的Heap有32G,于是我通過(guò)慢慢調(diào)整,最終在很小的內(nèi)存下也能重現(xiàn)出來(lái)。

Demo

測(cè)試代碼如下:

正如我上面注釋里寫的JVM參數(shù),控制新生代200M,老生代300M,老生代使用率達(dá)到90%的時(shí)候觸發(fā)CMS GC,大家可以跑跑看,這種情況下會(huì)發(fā)現(xiàn)不斷做CMS GC,但是老生代就是不降下去,但是只要你主動(dòng)觸發(fā)一次Full GC,老生代立馬就會(huì)回收。

當(dāng)allocateMemory方法執(zhí)行完之后,期待的結(jié)果是gc之后List及里面的byte數(shù)組都應(yīng)該被回收掉,可是事實(shí)并不是這樣的。

初步定位

這段代碼非常簡(jiǎn)單,我翻來(lái)覆去地看著這段代碼,視圖想改變點(diǎn)什么,能讓問(wèn)題出現(xiàn)峰回路轉(zhuǎn),我不斷地控制for循環(huán)的次數(shù)和每次分配的內(nèi)存大小,最終我將目標(biāo)轉(zhuǎn)移到那個(gè)ArrayList上,List里有個(gè)數(shù)組,在add過(guò)程中如果發(fā)現(xiàn)數(shù)組不夠了,于是會(huì)進(jìn)行擴(kuò)容,那擴(kuò)容就是創(chuàng)建新的數(shù)組,將老的對(duì)象放到新數(shù)組里,那我試想要是不做擴(kuò)容會(huì)不會(huì)有問(wèn)題?于是我開始調(diào)整ArrayList的初始化大小,當(dāng)我調(diào)到一定大小,保證在add過(guò)程中不會(huì)做擴(kuò)容,問(wèn)題真出現(xiàn)了反轉(zhuǎn),居然能正?;厥樟?,比如上面的demo,將數(shù)組長(zhǎng)度設(shè)置為len,那結(jié)果就完全不一樣了,老生代很快就被回收了。

那目標(biāo)能鎖定到數(shù)組擴(kuò)容了

數(shù)組擴(kuò)容

ArrayList里的數(shù)組擴(kuò)容,使用的是System.arrayCopy調(diào)用,這是一個(gè)native方法,在java層面創(chuàng)建一個(gè)新的長(zhǎng)度的數(shù)組,然后將老數(shù)組和新數(shù)組都傳進(jìn)去,在native里將老數(shù)組里的元素指針拷貝到新數(shù)組里,其實(shí)做的是淺拷貝,反復(fù)看native這塊實(shí)現(xiàn),也基本解釋不通那個(gè)現(xiàn)象,一度懷疑我對(duì)GC的理解了,是不是有哪些細(xì)節(jié)沒(méi)有注意到。

經(jīng)過(guò)我內(nèi)存dump分析,發(fā)現(xiàn)上面Demo里的List對(duì)象確實(shí)被回收了,但是List里的數(shù)組沒(méi)有被回收,這個(gè)數(shù)組里的byte數(shù)組都沒(méi)有被回收。

原來(lái)是這個(gè)鬼

帶著百思不得其解的疑惑和我們組同事討論,看看還有沒(méi)有其他可能的沒(méi)考慮到疑惑點(diǎn),開始也都覺(jué)得疑惑,后來(lái)傳勝突然想到會(huì)不會(huì)是存在跨代引用的問(wèn)題,于是回過(guò)來(lái)仔細(xì)再想想每個(gè)步驟,好像還真有可能,因?yàn)閭鹘oSystem.arrayCopy的新數(shù)組是在java層面構(gòu)建傳進(jìn)來(lái)的,在新生代分配的可能性***,這樣再加上拷貝僅僅是淺拷貝,那么老生代里的byte數(shù)組因?yàn)榇嬖谛律镄聲M的引用,那僅僅做CMS GC就不可能回收這些老生代的對(duì)象了,因?yàn)镃MS GC的一個(gè)gc root就是新生代里的對(duì)象。

那何解

至此終于抓出了那個(gè)鬼,于是想應(yīng)對(duì)策略,既然這樣,只要保證在cms gc回收old之前做一次ygc就能保證新生代里的那個(gè)新數(shù)組被回收而沒(méi)有指向老生代那些byte數(shù)組,那么這些數(shù)組就能正常被cms gc回收了,所以加上-XX:+CMSScavengeBeforeRemark即可解此問(wèn)題。

【本文是專欄作者李嘉鵬的原創(chuàng)文章,轉(zhuǎn)載請(qǐng)通過(guò)微信公眾號(hào)(你假笨,id:lovestblog)聯(lián)系作者本人獲取授權(quán)】


網(wǎng)頁(yè)題目:又抓了一個(gè)導(dǎo)致頻繁GC的鬼--數(shù)組動(dòng)態(tài)擴(kuò)容
標(biāo)題網(wǎng)址:http://www.5511xx.com/article/dhdgcdd.html