JVM(2)-垃圾收集器與內(nèi)存分配策略

2018-05-09

一、垃圾收集器

1.如何確定對(duì)象已死

1.1.引用計(jì)數(shù)法-Reference Counting

給對(duì)象添加一個(gè)引用計(jì)數(shù)器怒炸,當(dāng)有新的地方引用它時(shí)阅羹,引用計(jì)數(shù)器加1捏鱼,當(dāng)引用失效時(shí)穷躁,計(jì)數(shù)器減1因妇,任意時(shí)刻計(jì)數(shù)器為0的對(duì)象就是不可能被再使用了婚被。這種方式實(shí)現(xiàn)簡(jiǎn)單且高效址芯,但是很難解決循環(huán)引用的問(wèn)題谷炸,例如有兩個(gè)對(duì)象A、B拓颓,除了相互引用之外驶睦,并沒(méi)有可達(dá)引用可以訪問(wèn)到它們中的任意一個(gè),這種情況下其實(shí)它們已經(jīng)是垃圾對(duì)象缠导,但是它們的引用計(jì)數(shù)器都不為零僻造。

1.2.可達(dá)性分析-Reachability Analysis

這個(gè)方法的基本思想是通過(guò)一系列的稱為 “GC Root”的對(duì)象作為起點(diǎn)嫡意,從這些節(jié)點(diǎn)往下搜索捣辆,所經(jīng)過(guò)的路徑稱為引用鏈,當(dāng)一個(gè)對(duì)象到“GC Root”沒(méi)有任何引用鏈相連時(shí)旧巾,則證明此對(duì)象是不可用的鲁猩。這一些列GC Root對(duì)象是哪些對(duì)象呢罢坝?

  • 虛擬機(jī)棧(棧幀中的本地變量表)中引用的對(duì)象
  • 方法區(qū)中的靜態(tài)屬性引用的對(duì)象
  • 方法區(qū)中常量引用的對(duì)象
  • 本地方法區(qū)中JNI(即一般說(shuō)的Native方法)引用的對(duì)象

note: 關(guān)于Java中的4中引用可參考文章《Java中的4種引用類型》

2.生存還是死亡

  1. 當(dāng)一個(gè)對(duì)象與GC Root沒(méi)有任何引用鏈時(shí)隙券,那么它會(huì)被第一次標(biāo)記并且進(jìn)一步篩選闹司,篩選的條件是此對(duì)象有沒(méi)有必要執(zhí)行finalize()方法游桩。當(dāng)對(duì)象沒(méi)有覆蓋finalize()方法或者finalize()方法已經(jīng)被調(diào)虛擬機(jī)調(diào)用過(guò)借卧,虛擬機(jī)將這兩種情況視為“沒(méi)有必要執(zhí)行”。
  2. 若有必要執(zhí)行陪每,則將對(duì)象放置一個(gè)F-Queue的隊(duì)列中奶稠,并在稍后有虛擬機(jī)自動(dòng)建立的锌订、優(yōu)先級(jí)低的Finalizer線程去執(zhí)行辆飘,但并不承諾等待它運(yùn)行結(jié)束蜈项,因?yàn)椴恢纅inalize()方法的的耗時(shí)紧卒,盲目等待有可能造成阻塞诗祸。
  3. finalize()方法是對(duì)象逃脫死亡命運(yùn)的最后一次機(jī)會(huì)直颅,如果在finalize()方法中成功拯救了自己功偿,那就可以繼續(xù)存活械荷,如果沒(méi)有逃脫,那么它就真的被回收了征堪。

3.方法區(qū)回收

  1. 廢棄常量回收佃蚜,當(dāng)一個(gè)常量沒(méi)有被任意一個(gè)引用變量引用時(shí)着绊,此常量就是廢棄常量归露;

  2. 無(wú)用類卸載,無(wú)用類要滿足下面3個(gè)條件:

  • 該類的所有實(shí)例都被回收了恐锦,即Java堆中不存在該類的任何實(shí)例一铅;
  • 加載該類的ClassLoader已經(jīng)被回收;
  • 該類所對(duì)應(yīng)的java.lang.Class對(duì)象沒(méi)有任何地方被引用肮之,無(wú)法在任何地方通過(guò)發(fā)射訪問(wèn)該類的方法戈擒。

4.垃圾回收算法

4.1.標(biāo)記-清除(Mark-Sweep)

首先標(biāo)記所有可回收的對(duì)象筐高,在標(biāo)記完成后凯傲,統(tǒng)一回收冰单。
特點(diǎn):標(biāo)記清除這兩個(gè)過(guò)程效率都不高灸促,另外一點(diǎn)就是出現(xiàn)內(nèi)存碎片化問(wèn)題荒叼;

4.2.復(fù)制算法(Coping)

將可用內(nèi)存分為大小相等的兩塊被廓,只使用其中一塊萝玷,當(dāng)這一塊用完時(shí)蜓斧,將還存活的對(duì)象賦值到另外一塊中挎春,然后在把這一塊上已使用的一次回收掉。
特點(diǎn):實(shí)現(xiàn)簡(jiǎn)單能庆、高效搁胆,但這使得可用內(nèi)存變?yōu)樵瓉?lái)的一半丰涉,代價(jià)有點(diǎn)兒高。
現(xiàn)代商業(yè)虛擬機(jī)在新生代中采用這用算法回收肛度,將新生代按照 8:1 的比例分為 Eden 區(qū)和兩個(gè) Survivor 區(qū),每次只使用Eden和其中一個(gè)Survivor冠骄,當(dāng)使用完時(shí)加袋,將Eden和Survivor上的存活對(duì)象復(fù)制到另外一個(gè)Survivor上扁誓,如果存活的對(duì)象超過(guò)Survivor的大小蝗敢,則使用老年代寿谴。這樣每次使用的內(nèi)存就是原來(lái)的90%讶泰,浪費(fèi)的只有10%峻厚。

4.3.標(biāo)記-整理(Mark-Compact)

標(biāo)記過(guò)程與4.1類似惠桃,但后續(xù)過(guò)程是讓所有存活對(duì)象向一端移動(dòng),讓后直接清理掉邊界以外的內(nèi)存。

4.4.分代回收算法

這并不是一種新的思想辜王,而是根據(jù)具體的場(chǎng)景采用合適的回收算法劈狐。Java虛擬機(jī)一般把堆分為新生代和老年代,新生代的特點(diǎn)是每次垃圾收集時(shí)都發(fā)現(xiàn)大批對(duì)象死去呐馆,存活率低肥缔,適合采用復(fù)制算法;而老年代存活率很高汹来,則采用“標(biāo)記-清除”或者“標(biāo)記-整理”算法來(lái)進(jìn)行回收续膳。

5.HotSpot實(shí)現(xiàn)

5.1根節(jié)點(diǎn)枚舉

Stop the world,OopMap收班,不會(huì)為每條指令生成對(duì)應(yīng)的OopMap坟岔,只在特定的位置記錄這些信息,即安全點(diǎn)。

5.2.安全點(diǎn)

搶占試中斷啼辣,在發(fā)生GC時(shí)艾恼,中斷所用用戶線程柳爽,如果發(fā)現(xiàn)某個(gè)線程不在安全點(diǎn),則恢復(fù)此線程柿赊,讓其跑到安全點(diǎn)∫忍簦現(xiàn)在基本沒(méi)有虛擬機(jī)這個(gè)干郑象。
主動(dòng)式中斷团南,當(dāng)發(fā)生GC時(shí),只是設(shè)置標(biāo)記位,讓用戶線程自己在安全點(diǎn)檢查這個(gè)標(biāo)記,如果是ture則自己中斷掛起,另外一個(gè)檢測(cè)的地方時(shí)需要分配內(nèi)存的地方。

5.3.安全區(qū)域

SafePoint似乎能很好的解決進(jìn)入GC的問(wèn)題,但試想這樣一個(gè)場(chǎng)景缎玫,當(dāng)某些線程處于sleep或者blocked狀態(tài)時(shí)煞躬,虛擬機(jī)很難說(shuō)等待這些線程得到CUP資源并跑到附近的安全點(diǎn)上雷客,這個(gè)時(shí)間是不確定的部逮,這就引入了安全區(qū)域的概念颅和,當(dāng)一個(gè)線程進(jìn)入安全區(qū)域時(shí)教届,標(biāo)記位自己在安全區(qū)萤衰,發(fā)生GC時(shí),就不用管在安全區(qū)域的線程了,當(dāng)要離開安全區(qū)時(shí)它檢查是否已經(jīng)完成了GC椅邓,否則中斷掛起等待绰精。

6.垃圾收集器

來(lái)源于: https://blogs.oracle.com/jonthecollector/our-collectors

圖中的連線表示垃圾收集器可以配合工作

6.1.Serial

新生代收集器涉馁,單線程GC,采用復(fù)制算法好渠,所用用戶線程跑到SafePoint中斷杆烁,然后執(zhí)行GC勺良,GC完恢復(fù)用戶線程掌实,這會(huì)導(dǎo)致Stop The World父丰。

6.2.ParNew

多線程版的 Serial蘑斧。

6.3.Parallel Scavenge

新生代收集器竖瘾,復(fù)制算法庸论,并行多線程收集器聂示,看上去和ParNew一樣锋边,但它的關(guān)注點(diǎn)不一樣抹沪,前兩個(gè)收集器的關(guān)注點(diǎn)是盡量縮短GC導(dǎo)致用戶線程的停頓時(shí)間拟赊,而這個(gè)收集器的關(guān)注點(diǎn)是吞吐量,吞吐量 = 運(yùn)行用戶代碼時(shí)間 / (運(yùn)行用戶代碼時(shí)間 + 垃圾收集時(shí)間)借杰。

6.4.Serial Old

老年代收集器过吻,單線程,使用“標(biāo)記-整理”算法蔗衡。

6.5 Parallel Old

是Parallel Scavenge的老年代版本疮装,使用“標(biāo)記-整理”算法。

6.7 CMS

Concurrent Mark Sweep收集器粘都,關(guān)注點(diǎn)是獲得最短的回收停頓時(shí)間廓推,從名字就看得出來(lái)是“標(biāo)記-清除”算法,它運(yùn)作過(guò)程分為四個(gè)步驟:

  • 初始標(biāo)記(CMS initial mark)- Stop The World
  • 并發(fā)標(biāo)記(CMS concurrent mark)
  • 重新標(biāo)記(CMS remark)- Stop The World
  • 并發(fā)清除(CMS concurrent sweep)

在四個(gè)步驟中翩隧,其中并發(fā)標(biāo)記樊展、并發(fā)清除時(shí)間是相對(duì)較長(zhǎng)的,都是可以和用戶線程并發(fā)執(zhí)行的堆生,所以Stop The World時(shí)間是很短的专缠,總體上來(lái)看就是并發(fā)執(zhí)行的,這對(duì)要求響應(yīng)速度較快的應(yīng)用場(chǎng)景比較適合淑仆。CMS還遠(yuǎn)達(dá)不到完美涝婉,它有一下幾個(gè)缺點(diǎn):

  • 對(duì)CUP資源敏感,搶占CUP資源將導(dǎo)致用戶線程的CUP資源減少而變得緩慢蔗怠;
  • 無(wú)法處理浮動(dòng)垃圾墩弯,在并發(fā)回收垃圾時(shí),用戶線程會(huì)產(chǎn)生新的垃圾對(duì)象寞射,這些垃圾要等下次回收渔工;由于在并發(fā)回收的過(guò)程用戶線程還在工作,這就需要預(yù)留一定的內(nèi)存空間給用戶線程桥温,導(dǎo)致內(nèi)存空間利用率下降引矩;
  • CMS采用的是標(biāo)記-清除算法,這就導(dǎo)致內(nèi)存碎片化。若出現(xiàn)內(nèi)存空間還很多旺韭,但由于碎片化的情況氛谜,無(wú)法滿足大對(duì)象的分配,當(dāng)頂不住要觸發(fā)Full GC時(shí)開啟內(nèi)存碎片合并整理過(guò)程区端,這個(gè)過(guò)程是不能并發(fā)的值漫,會(huì)Stop The World。

6.8.G1

Garbage First珊燎,將內(nèi)存分為多個(gè)Region惭嚣,使用Remembered Set 避免全盤掃描,標(biāo)記-整理算法悔政。

  • 初始標(biāo)記(initial Marking)
  • 并發(fā)標(biāo)記(Concurrent Marking)
  • 最終標(biāo)記(Final Marking)
  • 篩選回收(Live Data Counting Evacuation)

優(yōu)點(diǎn):

  • 并行與并發(fā)晚吞,能充分利用CUP資源;
  • 空間整理谋国,與CMS的標(biāo)記-清理相比槽地,它采用的是標(biāo)記-整理,從局部Region來(lái)看又是復(fù)制算法芦瘾;
  • 可預(yù)測(cè)停頓捌蚊,可以讓使用這指定在長(zhǎng)度為M毫秒的是時(shí)間內(nèi),垃圾收集時(shí)間不能超過(guò)N毫秒近弟;

二缅糟、內(nèi)存分配策略

  1. 對(duì)象優(yōu)先新生代Eden區(qū)分配
    大多數(shù)情況下,對(duì)象在新生代Eden區(qū)分配祷愉,若Eden區(qū)無(wú)法分配窗宦,則虛擬機(jī)會(huì)觸發(fā)一次Minor GC。

Minor GC-新生代二鳄; Major GC/Full GC-老年代

  1. 大對(duì)象直接直接進(jìn)入老年代赴涵,大對(duì)象的界定可通過(guò)參數(shù)設(shè)定;
  2. 長(zhǎng)期存活的對(duì)象進(jìn)入老年代订讼,對(duì)象的年齡髓窜,Minor GC一次且能被Survivor分區(qū)容納則加1,默認(rèn)是15歲進(jìn)入老年代欺殿;
  3. 動(dòng)態(tài)年齡判斷寄纵,虛擬機(jī)并非永遠(yuǎn)要求對(duì)象的年齡到達(dá)了MaxTenuringThreshold才能晉升老年代,如果相同年齡的對(duì)象總時(shí)占據(jù)Survivor分區(qū)的一半及以上祈餐,年齡大于或者等于改年齡的對(duì)象就可以直接進(jìn)入老年代擂啥,無(wú)須等到年齡到達(dá)MaxTenuringThreshold;
  4. 空間分配擔(dān)保帆阳,處理Minor GC的風(fēng)險(xiǎn)問(wèn)題,老年代為新生代擔(dān)保,根據(jù)具體情況看是是否執(zhí)行Full GC蜒谤,比如老年代的剩余連續(xù)空間比新生代大山宾,那就沒(méi)有必要Full GC,這種情況下Minor GC是沒(méi)有風(fēng)險(xiǎn)的鳍徽。

參考:https://blogs.oracle.com/jonthecollector/our-collectors

上一篇:JVM(1)-運(yùn)行時(shí)數(shù)據(jù)區(qū)
下一篇:JVM(3)-類加載機(jī)制

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末资锰,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子阶祭,更是在濱河造成了極大的恐慌绷杜,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,383評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件濒募,死亡現(xiàn)場(chǎng)離奇詭異鞭盟,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)瑰剃,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門齿诉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人晌姚,你說(shuō)我怎么就攤上這事粤剧。” “怎么了挥唠?”我有些...
    開封第一講書人閱讀 157,852評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵抵恋,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我宝磨,道長(zhǎng)弧关,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,621評(píng)論 1 284
  • 正文 為了忘掉前任懊烤,我火速辦了婚禮梯醒,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘腌紧。我一直安慰自己茸习,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,741評(píng)論 6 386
  • 文/花漫 我一把揭開白布壁肋。 她就那樣靜靜地躺著号胚,像睡著了一般。 火紅的嫁衣襯著肌膚如雪浸遗。 梳的紋絲不亂的頭發(fā)上猫胁,一...
    開封第一講書人閱讀 49,929評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音跛锌,去河邊找鬼弃秆。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的菠赚。 我是一名探鬼主播脑豹,決...
    沈念sama閱讀 39,076評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼衡查!你這毒婦竟也來(lái)了瘩欺?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,803評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤拌牲,失蹤者是張志新(化名)和其女友劉穎俱饿,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體塌忽,經(jīng)...
    沈念sama閱讀 44,265評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡拍埠,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,582評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了砚婆。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片械拍。...
    茶點(diǎn)故事閱讀 38,716評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖装盯,靈堂內(nèi)的尸體忽然破棺而出坷虑,到底是詐尸還是另有隱情,我是刑警寧澤埂奈,帶...
    沈念sama閱讀 34,395評(píng)論 4 333
  • 正文 年R本政府宣布迄损,位于F島的核電站,受9級(jí)特大地震影響账磺,放射性物質(zhì)發(fā)生泄漏芹敌。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,039評(píng)論 3 316
  • 文/蒙蒙 一垮抗、第九天 我趴在偏房一處隱蔽的房頂上張望氏捞。 院中可真熱鬧,春花似錦冒版、人聲如沸液茎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)捆等。三九已至奏篙,卻和暖如春潭袱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背股淡。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工挺狰, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留明郭,地道東北人买窟。 一個(gè)月前我還...
    沈念sama閱讀 46,488評(píng)論 2 361
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像达址,于是被迫代替她去往敵國(guó)和親蔑祟。 傳聞我的和親對(duì)象是個(gè)殘疾皇子趁耗,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,612評(píng)論 2 350

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