GC總結(jié)

原文:為知筆記外鏈

對(duì)象回收設(shè)計(jì)兩類操作:

  1. 判斷對(duì)象是否可回收
  2. 執(zhí)行回收

判斷對(duì)象可被回收的算法:

引用計(jì)數(shù)法 【效率高滑燃,無法解決相互引用問題】

給對(duì)象添加一個(gè)引用計(jì)數(shù)器,每當(dāng)有地方引用則該計(jì)數(shù)器值+1溯警,當(dāng)引用失效則-1;計(jì)數(shù)器為0的對(duì)象不可再被使用甲锡,可以被回收拒名。

可達(dá)性分析算法

通過一系列成為 “GC Root" 的對(duì)象作為起點(diǎn),從這些節(jié)點(diǎn)開始向下搜索锄奢,搜索所走過的路徑為 引用鏈(MAT中的支配樹)失晴,當(dāng)一個(gè)對(duì)象到 GC Roots 沒有任何引用鏈相連,即GC Roots到這個(gè)對(duì)象不可達(dá)時(shí)拘央,則證明此對(duì)象不可用涂屁。

可作為GC Roots的對(duì)象包括:

  1. 虛擬機(jī)棧(棧幀中的本地變量表)中引用的對(duì)象。

  2. 方法區(qū)中類靜態(tài)屬性引用的對(duì)象灰伟。

  3. 方法區(qū)中常量引用的對(duì)象拆又。

  4. 本地方法棧中JNI(Native方法)引用的對(duì)象。

引用:
  1. 強(qiáng)引用:GC永遠(yuǎn)不會(huì)回收掉的被引用的對(duì)象【通過 new 創(chuàng)建的對(duì)象】

  2. 軟引用【SoftReference】:有用但非必須的對(duì)象栏账。在系統(tǒng)將要發(fā)生內(nèi)存溢出之前帖族,將會(huì)把這些對(duì)象列進(jìn)回收范圍中進(jìn)行第二次回收。如果這次回收還沒有足夠的內(nèi)存挡爵,才會(huì)拋出內(nèi)存溢出異常竖般。

  3. 弱引用【W(wǎng)eakReference】:非必須的對(duì)象。強(qiáng)度比軟引用弱茶鹃,被弱引用關(guān)聯(lián)的對(duì)象只能存活到下次垃圾收集發(fā)生之前涣雕。當(dāng)垃圾回收時(shí),無論當(dāng)前內(nèi)存是否足夠闭翩,都會(huì)回收掉被弱引用關(guān)聯(lián)的對(duì)象挣郭。

  4. 虛引用【PhantomReference】:無用,唯一目的就是能在被收集器回收時(shí)受到一個(gè)系統(tǒng)通知疗韵。

即使在可達(dá)性分析算法中不可達(dá)的對(duì)象兑障,也并非是“非死不可”的,這時(shí)它們會(huì)處于 ”緩刑“ 階段,要真正宣告一個(gè)對(duì)象死亡流译,至少要經(jīng)歷兩次標(biāo)記過程:如果對(duì)象在進(jìn)行可達(dá)性分析之后發(fā)現(xiàn)沒有與GC Roots相連接的引用鏈逞怨,那它將被第一次標(biāo)記并且進(jìn)行一次 篩選 ,篩選的條件是此對(duì)象是否有必要執(zhí)行 finalize() 方法先蒋『眨【當(dāng)對(duì)象沒有覆蓋 finalize() 方法,或者 finalize() 方法已被虛擬機(jī)調(diào)用過竞漾,jvm將這兩種情況視為 沒有必要執(zhí)行 】眯搭。
如果該對(duì)象被判定為有必要執(zhí)行 finalize() 方法,那么該對(duì)象會(huì)被放置在一個(gè) F-Queue 的隊(duì)列中业岁,并在稍后由一個(gè)虛擬機(jī)自動(dòng)建立的鳞仙、低優(yōu)先級(jí)的 Finalizer 線程去執(zhí)行它”适保【所謂執(zhí)行是指jvm會(huì)觸發(fā)該方法棍好,但并不承諾會(huì)等待它運(yùn)行結(jié)束,因?yàn)槿绻粋€(gè)對(duì)象在 finalize() 方法中執(zhí)行緩慢或死循環(huán)允耿,將可能導(dǎo)致F-Queue隊(duì)列中其他對(duì)象永久處于等待借笙,甚至導(dǎo)致整個(gè)內(nèi)存回收系統(tǒng)崩潰〗衔】
finalize() 方法時(shí)對(duì)象逃脫死亡命運(yùn)的最后一次機(jī)會(huì)业稼,稍后GC將對(duì)F-Queue中的對(duì)象進(jìn)行第二次小規(guī)模標(biāo)記,如果對(duì)象要在finalize()方法中成功拯救自己--只要重新與引用鏈上的任何一個(gè)對(duì)象建立關(guān)聯(lián)即可蚂蕴,之后在第二次標(biāo)記時(shí)會(huì)被移除“即將回收”的集合低散。
如果對(duì)象這時(shí)還沒有逃脫,基本上就真的會(huì)被回收了【u are done】骡楼。
任何一個(gè)對(duì)象的finalize()方法都只會(huì)被系統(tǒng)自動(dòng)調(diào)用一次熔号,如果對(duì)象面臨下一次回收,則該方法不會(huì)再被執(zhí)行鸟整。

垃圾收集算法:【執(zhí)行回收】

標(biāo)記-清除算法
最基礎(chǔ)的收集算法引镊。算法分為 “標(biāo)記” 和 “清除” 兩個(gè)階段:首先標(biāo)記出所有需要回收的對(duì)象,在標(biāo)記完成后統(tǒng)一回收所有被標(biāo)記的對(duì)象篮条〉芡罚【標(biāo)記過程如上】。
標(biāo)記-清除過程
存在問題:
  1. 效率不高兑燥。標(biāo)記和清除效率都不高。

  2. 空間問題:標(biāo)記清除之后會(huì)產(chǎn)生大量不連續(xù)的內(nèi)存碎片琴拧,空間碎片太多可能會(huì)導(dǎo)致以后程序運(yùn)行過程中需要分配較大對(duì)象時(shí)降瞳,無法找到足夠連續(xù)內(nèi)存而不得不提前觸發(fā)另一次垃圾收集動(dòng)作。

復(fù)制算法【新生代】
將可用內(nèi)存按容量劃分為大小相等的兩塊,每次只使用其中一塊挣饥。當(dāng)這一塊的內(nèi)存用完了除师,就將還存活著的對(duì)象復(fù)制到另外一塊上邊,然后再把已使用過的內(nèi)存空間一次清理掉扔枫。
復(fù)制算法

好處:每次對(duì)整個(gè)半?yún)^(qū)進(jìn)行內(nèi)存回收汛聚,不必考慮內(nèi)存碎片等情況,只要移動(dòng)堆頂指針短荐,按順序分配內(nèi)存即可倚舀,實(shí)現(xiàn)簡(jiǎn)單,運(yùn)行高效忍宋。

不足:代價(jià)是將內(nèi)存縮小一半痕貌。

目前主流均采用該收集算法回收新生代【分代收集】。IBM研究表明糠排,新生代中的對(duì)象98%都是朝生夕死舵稠,所以不必按照1:1的比例來劃分內(nèi)存空間,而是將內(nèi)存劃分為一塊兒比較大的 Eden空間和兩塊較小的Survivor空間入宦,每次使用 Eden 和其中一塊Survivor空間哺徊。當(dāng)回收時(shí),將Eden和Survivor中還存活著的對(duì)象一次性的復(fù)制到另外一塊Survivor空間上乾闰,最后清理掉Eden和剛剛使用過的Survivor空間落追。HotSpot虛擬機(jī)默認(rèn)比例是8:1,也就是每次新生代中可用內(nèi)存空間為整個(gè)新生代容量的90%(80%+10%)汹忠,只有10%的內(nèi)存會(huì)被“浪費(fèi)”
內(nèi)存的分配擔(dān)保機(jī)制:如果另外一塊兒Survivor空間沒有足夠空間存放上次新生代收集下來的存活的對(duì)象時(shí)淋硝,這些對(duì)象會(huì)通過 分配擔(dān)保機(jī)制 進(jìn)入老年代。
標(biāo)記-整理算法【老年代】

復(fù)制收集算法在對(duì)象存活率較高時(shí)就要進(jìn)行較多的復(fù)制操作宽菜,效率會(huì)變很低谣膳。如果不想浪費(fèi)50%的空間,就需要額外的空間進(jìn)行分配擔(dān)保铅乡,以應(yīng)對(duì)被使用的內(nèi)存中所有對(duì)象都100%存活的極端情況继谚,所以老年代一般不直接選用這種算法

標(biāo)記過程與 標(biāo)記-清除 算法一致,但后續(xù)步驟不是直接對(duì)可回收對(duì)象進(jìn)行清理阵幸,而是讓所有存活的對(duì)象都向一端移動(dòng)花履,然后直接清理掉端邊界以外的內(nèi)存。示意圖如下:
標(biāo)記-整理算法

分代收集算法

目前商業(yè)虛擬機(jī)都采用的垃圾收集算法挚赊。根據(jù)對(duì)象存活周期的不同將內(nèi)存劃分為幾塊诡壁。將Java堆分為新生代和老年代。這樣就可以根據(jù)各個(gè)年代的特點(diǎn)采用最適當(dāng)?shù)氖占惴ㄜ睢T谛律忻们洌看卫占瘯r(shí)都會(huì)有大批對(duì)象死去旺矾,只有少量存活,則選用復(fù)制算法夺克,只需付出少量存活對(duì)象的復(fù)制成本即可箕宙。而老年代中因?yàn)閷?duì)象存活率高、沒有額外空間對(duì)它進(jìn)行分配擔(dān)保铺纽,因此必須使用標(biāo)記-清理或標(biāo)記-整理算法進(jìn)行回收柬帕。

臭名昭著的 STW (Stop the world)

可達(dá)性分析時(shí),必須在一個(gè)能確保一致性的快照中進(jìn)行---即整個(gè)分析期間整個(gè)執(zhí)行系統(tǒng)看起來就像被凍結(jié)在某個(gè)時(shí)間點(diǎn)上狡门,不可以出現(xiàn)分析過程中對(duì)象引用關(guān)系還在不斷變化的情況陷寝,否則分析結(jié)果準(zhǔn)確性就無法保證。這點(diǎn)是導(dǎo)致GC進(jìn)行時(shí)必須停頓所有Java執(zhí)行線程的一個(gè)重要原因融撞。即使在號(hào)稱幾乎不會(huì)發(fā)生停頓的CMS收集器中盼铁,枚舉根節(jié)點(diǎn)時(shí)也必須停頓。

安全點(diǎn):但程序執(zhí)行時(shí)并非在所有的地方都能停頓下來開始GC尝偎,只有到達(dá)安全點(diǎn)(SafePoint)才能暫停饶火。讓所有線程在GC發(fā)生時(shí)跑到安全點(diǎn)的方法有:搶先式中斷和主動(dòng)式中斷。

內(nèi)存分配與回收策略

  • 對(duì)象優(yōu)先在Eden分配致扯。大多數(shù)情況下肤寝,對(duì)象在新生代Eden區(qū)中分配。當(dāng)Eden區(qū)沒有足夠空間進(jìn)行分配時(shí)抖僵,虛擬機(jī)將發(fā)起一次Minor GC.

  • 大對(duì)象直接進(jìn)入老年代鲤看。需要大量連續(xù)內(nèi)存空間的Java對(duì)象,如很長(zhǎng)的字符串或數(shù)組耍群,將被分配到老年代义桂。

  • 長(zhǎng)期存活的對(duì)象將進(jìn)入老年代。虛擬機(jī)給每個(gè)對(duì)象定義了一個(gè)對(duì)象年齡計(jì)數(shù)器蹈垢。如果對(duì)象在Eden出生并且經(jīng)過依次Minor GC后仍然存活慷吊,并且能被Survivor容納,將被移動(dòng)到Survivor空間中曹抬,并且對(duì)象年齡設(shè)為1溉瓶。對(duì)象在Survivor區(qū)中每 “熬過” 依次Minor GC,年齡就會(huì)+1谤民,當(dāng)年齡增加到一定程度(默認(rèn)15堰酿,可通過 -XX:MaxTenuringThreshold設(shè)置),就會(huì)被晉升到老年代中张足。

  • 如果在Survivor空間中相同年齡所有對(duì)象大小的總和大于Survivor空間的一半触创,年齡大于或等于該年齡的對(duì)象可以直接進(jìn)入老年代,無須等到 MaxTenuringThreshold 中要求的年齡为牍。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末哼绑,一起剝皮案震驚了整個(gè)濱河市顺饮,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌凌那,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,084評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件吟逝,死亡現(xiàn)場(chǎng)離奇詭異帽蝶,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)块攒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門励稳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人驹尼,你說我怎么就攤上這事∨优唬” “怎么了新翎?”我有些...
    開封第一講書人閱讀 163,450評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)住练。 經(jīng)常有香客問我地啰,道長(zhǎng),這世上最難降的妖魔是什么讲逛? 我笑而不...
    開封第一講書人閱讀 58,322評(píng)論 1 293
  • 正文 為了忘掉前任亏吝,我火速辦了婚禮,結(jié)果婚禮上盏混,老公的妹妹穿的比我還像新娘蔚鸥。我一直安慰自己,他們只是感情好许赃,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,370評(píng)論 6 390
  • 文/花漫 我一把揭開白布止喷。 她就那樣靜靜地躺著,像睡著了一般图焰。 火紅的嫁衣襯著肌膚如雪启盛。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,274評(píng)論 1 300
  • 那天技羔,我揣著相機(jī)與錄音僵闯,去河邊找鬼。 笑死藤滥,一個(gè)胖子當(dāng)著我的面吹牛鳖粟,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播拙绊,決...
    沈念sama閱讀 40,126評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼向图,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼泳秀!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起榄攀,我...
    開封第一講書人閱讀 38,980評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤嗜傅,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后檩赢,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體吕嘀,經(jīng)...
    沈念sama閱讀 45,414評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,599評(píng)論 3 334
  • 正文 我和宋清朗相戀三年贞瞒,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了偶房。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,773評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡军浆,死狀恐怖棕洋,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情乒融,我是刑警寧澤掰盘,帶...
    沈念sama閱讀 35,470評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站赞季,受9級(jí)特大地震影響庆杜,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜碟摆,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,080評(píng)論 3 327
  • 文/蒙蒙 一晃财、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧典蜕,春花似錦断盛、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至轩缤,卻和暖如春命迈,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背火的。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工壶愤, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人馏鹤。 一個(gè)月前我還...
    沈念sama閱讀 47,865評(píng)論 2 370
  • 正文 我出身青樓征椒,卻偏偏與公主長(zhǎng)得像湃累,于是被迫代替她去往敵國(guó)和親勃救。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,689評(píng)論 2 354

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

  • 1.什么是垃圾回收蒙秒? 垃圾回收(Garbage Collection)是Java虛擬機(jī)(JVM)垃圾回收器提供...
    簡(jiǎn)欲明心閱讀 89,485評(píng)論 17 311
  • JVM架構(gòu) 當(dāng)一個(gè)程序啟動(dòng)之前,它的class會(huì)被類裝載器裝入方法區(qū)(Permanent區(qū))晕讲,執(zhí)行引擎讀取方法區(qū)的...
    cocohaifang閱讀 1,664評(píng)論 0 7
  • 原文閱讀 前言 這段時(shí)間懈怠了溉躲,罪過! 最近看到有同事也開始用上了微信公眾號(hào)寫博客了,挺好的~給他們點(diǎn)贊箭券,這博客我...
    碼農(nóng)戲碼閱讀 5,962評(píng)論 2 31
  • 概述 觀察Java內(nèi)存運(yùn)行時(shí)區(qū)域的各個(gè)部分,其中程序計(jì)數(shù)器辩块、Java虛擬機(jī)棧蛔六、本地方法棧3個(gè)區(qū)域隨線程而生,隨線程...
    Steven1997閱讀 597評(píng)論 0 0
  • GC GC(Garbage Collection)是Java虛擬機(jī)(JVM)垃圾回收器提供的一種用于在空閑時(shí)間不定...
    紅Bean閱讀 897評(píng)論 0 12