深入淺出 JVM GC(2)

# 前言

深入淺出 JVM GC(1) 中朦前,限于上篇文章的篇幅唬格,我們留下了一個(gè)問(wèn)題 : 如何回收? 這篇文章將重點(diǎn)講述這個(gè)問(wèn)題仓坞。

在上篇文章中背零,我們也列出了一些大綱,今天我們就按照那個(gè)大綱來(lái)逐個(gè)講解无埃。在此徙瓶,我將大綱復(fù)制過(guò)來(lái)毛雇。

垃圾回收算法

  1. 標(biāo)記清除算法
  2. 復(fù)制算法
  3. 標(biāo)記整理算法
  4. 分代收集算法(堆如何分代)

有哪些垃圾收集器

  1. Serial 串行收集器(只適用于堆內(nèi)存256m 以下的 JVM )
  2. ParNew 并行收集器(Serial 收集器的多線程版本)
  3. Parallel Scavenge (PS 收集器,該收集器以吞吐量為主要目的侦镇,是1.8的默認(rèn) GC)
  4. CMS 收集器(該收集器全稱 Concurrent Mark Sweep灵疮,是一種關(guān)注最短停頓時(shí)間的垃圾收集器)
  5. G1 收集器(JDK 9 的默認(rèn) GC)

有哪些GC

  1. Young GC(又稱 YGC,minor GC壳繁,年輕代 GC)
  2. Old GC (老年代 GC震捣,只有 CMS 才會(huì)單獨(dú)回收 Old 區(qū))
  3. Full GC(又稱 major GC)
  4. Mixed GC(混合 GC,G1 收集器獨(dú)有)

1. 有哪些垃圾回收算法

  1. 標(biāo)記清除算法
  2. 復(fù)制算法
  3. 標(biāo)記整理算法
  4. 分代收集算法(堆如何分代)
1. 標(biāo)記清除算法

GC 中最基礎(chǔ)的算法就是標(biāo)記-清除算法闹炉,所謂標(biāo)記清除蒿赢,就是通過(guò)可達(dá)性分析,標(biāo)記哪些是垃圾對(duì)象剩胁,然后清除诉植。之所以說(shuō)是最簡(jiǎn)單的算法,是因?yàn)楹竺娴膸追N算法都是基于它的昵观。

但是這個(gè)算法有2個(gè)不足之處:1. 碎片問(wèn)題晾腔,標(biāo)記清除之后會(huì)導(dǎo)致大量?jī)?nèi)存不連續(xù)的碎片,空間碎片太多會(huì)導(dǎo)致分配大對(duì)象時(shí)無(wú)法找到足夠的連續(xù)內(nèi)存從而提前觸發(fā) Full GC (此 GC 嚴(yán)重影響應(yīng)用性能)啊犬。2. 效率問(wèn)題灼擂,標(biāo)記和清除這兩個(gè)過(guò)程的效率都不高。我們通過(guò)一幅圖來(lái)看看標(biāo)記清除的算法:

標(biāo)記清除算法示意圖

可以從上圖看出觉至,回收后剔应,出現(xiàn)了大量的內(nèi)存不連續(xù)的內(nèi)存塊。

2. 復(fù)制算法

為了解決效率問(wèn)題语御,人們發(fā)明了一種復(fù)制算法(Coping)峻贮。它將可用內(nèi)存按容量劃分為大小相等的兩塊,每次只使用其中的一塊应闯。當(dāng)這一塊的用完了纤控,就開(kāi)始垃圾回收,將有用的對(duì)象復(fù)制到另一個(gè)空閑的內(nèi)存上碉纺,清空之前使用的內(nèi)存塊船万。這樣使得每次都對(duì)整個(gè)半?yún)^(qū)回收,而且也不用考慮內(nèi)存碎片問(wèn)題骨田,只需要移動(dòng)堆頂指針耿导,按順序分配即可,實(shí)現(xiàn)簡(jiǎn)單态贤,運(yùn)行高效舱呻。

但是凡事都是有缺點(diǎn)的,復(fù)制算法的缺點(diǎn)就是內(nèi)存縮小到了原來(lái)的一半抵卫,無(wú)法充分利用內(nèi)存空間狮荔。

總是有取舍的胎撇。

現(xiàn)代的所有商業(yè)虛擬機(jī)都是采用這種算法來(lái)回收新生代介粘≈呈希基于統(tǒng)計(jì)學(xué),人們得出99% 的對(duì)象都是朝生夕死的姻采,所以不需要留出那么大的空間保存存活的對(duì)象雅采,也就是不要1:1 的比例來(lái)劃分內(nèi)存。

通常的做法是:

將內(nèi)存分為一個(gè)較大的Eden(伊甸園)空間和兩塊較小的 Survivor(幸存區(qū))空間慨亲,每次使用 Eden 和其中一塊 Survivor 婚瓜,當(dāng)回收時(shí),將 Eden 和 Survivor 還存活著的對(duì)象一次性的復(fù)制到另外一塊 Survivor 空間刑棵,最后清理掉 Eden 和剛剛使用的 Survivor 空間巴刻。Hotspot 默認(rèn)的比例是 8:1:1,也就是說(shuō)蛉签,每次新生代可用內(nèi)存空間為新生代總空間的90%胡陪,只有10%的內(nèi)存會(huì)被浪費(fèi),從一定程度上解決了復(fù)制算法浪費(fèi)空間的問(wèn)題碍舍。

當(dāng)然柠座,98% 的對(duì)象可回收只是一般的情況下,我們無(wú)法保證每次回收都只有不多于 10% 的對(duì)象存活片橡,當(dāng) Survivor 空間不夠用時(shí)怎么辦呢妈经?肯定需要依賴其他內(nèi)存(老年代)進(jìn)行所謂的分配擔(dān)保(Handle Promotion)。

什么是分配擔(dān)保呢捧书?

如果另外一塊 Survivor 區(qū)域沒(méi)有足夠空間存放上一次新生代手機(jī)下來(lái)的存活對(duì)象時(shí)吹泡,這些對(duì)象將直接通過(guò)分配擔(dān)保機(jī)制進(jìn)入老年代。當(dāng)然经瓷,具體細(xì)節(jié)這句話無(wú)法詳細(xì)說(shuō)明爆哑,我們將會(huì)在之后闡述具體細(xì)節(jié)。

3. 標(biāo)記整理算法

從上面我們可以看出了嚎,復(fù)制算法的效率很高泪漂,請(qǐng)注意,該算法只有在對(duì)象存活率較低的時(shí)候(98% 對(duì)象可被回收)才能體現(xiàn)出效率歪泳。而如果一次 GC 活動(dòng)之后萝勤,存活對(duì)象很多,那么就需要復(fù)制大量的對(duì)象呐伞,很明顯敌卓,會(huì)導(dǎo)致效率不高;更關(guān)鍵的是伶氢,還需要額外的空間進(jìn)行分配擔(dān)保趟径。

所以瘪吏,存活對(duì)象時(shí)間很長(zhǎng)的老年代一般不使用該算法。

根據(jù)老年代的特點(diǎn)蜗巧,一般使用“標(biāo)記-整理(Mark-Compact)”算法掌眠,標(biāo)記過(guò)程仍然與 “標(biāo)記清除” 算法一樣,但我們知道幕屹,標(biāo)記清除算法會(huì)產(chǎn)生大量的內(nèi)存碎片蓝丙,對(duì)性能影響很大,所以標(biāo)記整理算法后續(xù)步驟不是直接對(duì)可回收對(duì)象進(jìn)行清理望拖,而是讓所有存活的對(duì)象像一個(gè)方向移動(dòng)渺尘,然后清理掉邊界之外的內(nèi)存。也就是將那些原來(lái)散落的對(duì)象移動(dòng)在一起说敏,讓碎片不再存在鸥跟。

可以說(shuō),標(biāo)記整理算法相對(duì)于標(biāo)記清除算法犧牲了一些性能盔沫,但卻避免了內(nèi)存碎片的產(chǎn)生医咨,在大部分場(chǎng)合,可抵消掉整理過(guò)程中產(chǎn)生的性能損耗迅诬。

4. 分代收集算法

上面我們提到了幾個(gè)名詞腋逆,新生代,老年代侈贷,這些就是分代算法中名詞惩歉。分代算法最主要的就是根據(jù)對(duì)象存活周期的不同將內(nèi)存分成幾塊,一般是把 Java 堆分成新生代和老年代俏蛮,這樣就可以根據(jù)各個(gè)年代的特點(diǎn)采用最適當(dāng)?shù)氖占惴ā?/p>

在新生代中撑蚌,每次垃圾收集都發(fā)現(xiàn)有大批對(duì)象死去,只有少量存活搏屑,那就選用復(fù)制算法争涌,只需要付出少量存活對(duì)象的復(fù)制成本就可以完成收集。而老年代中因?yàn)閷?duì)象存活率高辣恋,沒(méi)有額外空間對(duì)它進(jìn)行分配擔(dān)保亮垫,就必須使用“標(biāo)記清理” 或者 “標(biāo)記整理” 算法來(lái)進(jìn)行回收。

2. 有哪些垃圾收集器

上面說(shuō)的這些算法都是實(shí)現(xiàn)垃圾收集器的基礎(chǔ)伟骨。

如果說(shuō)收集算法是內(nèi)存回收的方法論饮潦,那么垃圾收集器就是內(nèi)存回收的具體實(shí)現(xiàn)。

Hotspot 虛擬機(jī)所包含的所有收集器如下圖:

Hotspot 所有 GC 組合

從上圖中看到携狭,一共有6種 GC 組合(忽略 G1 和 為CMS備份的 SerialOld 組合 )继蜡。

  1. Serial + Serial Old
  2. Serial + CMS
  3. ParNew + CMS
  4. ParNew + Serial Old
  5. Parallel Scavenge + Serial Old
  6. Parallel Scavenge + Parallel Old

大家看到這里,一定有個(gè)疑問(wèn),為什么需要這么多垃圾收集器稀并?

答案是:沒(méi)有任何一種垃圾收集器是完美的仅颇,沒(méi)有任何一種垃圾收集器適合所有的應(yīng)用情況。

每個(gè)應(yīng)用都需要自己的特定垃圾收集器碘举,因此忘瓦,可以說(shuō),GC 調(diào)優(yōu)是門(mén)藝術(shù)殴俱,沒(méi)有放之四海皆準(zhǔn)的 GC政冻。需要工程師們?nèi)ジ鶕?jù)應(yīng)用的特性不斷調(diào)優(yōu)枚抵。

這么多 GC 线欲,限于篇幅,我們將在 深入淺出 JVM GC(3) 中慢慢解釋汽摹。
這里只是列出一個(gè)大綱李丰。

接下來(lái)我們將說(shuō)說(shuō)關(guān)于 GC 的一些概念,方便閱讀后面的關(guān)于 GC 處理器的文章逼泣。

3. 有哪些GC

  1. Young GC(又稱 YGC趴泌,minor GC,年輕代 GC)
  2. Old GC (老年代 GC拉庶,只有 CMS 才會(huì)單獨(dú)回收 Old 區(qū))
  3. Full GC(又稱 major GC)
  4. Mixed GC(混合 GC嗜憔,G1 收集器獨(dú)有)

關(guān)于這些 GC 的分類,R 大一個(gè)回答比較清楚:Major GC和Full GC的區(qū)別是什么氏仗?觸發(fā)條件呢吉捶?

從大的方面講,GC 只分為兩種皆尔,一種是不收集整個(gè)堆呐舔,一種是收集整個(gè)堆。

Partial GC:并不收集整個(gè)GC堆的模式

  1. Young GC:只收集young gen的GC
  2. Old GC:只收集old gen的GC慷蠕。只有CMS的concurrent collection是這個(gè)模式
  3. Mixed GC:收集整個(gè)young gen以及部分old gen的GC珊拼。只有G1有這個(gè)模式

Full GC:收集整個(gè)堆,包括young gen流炕、old gen澎现、perm gen(如果存在的話)等所有部分的模式。

1. YGC

YGC 又稱 Young GC 每辟,minor GC 剑辫,年輕代 GC。顧名思義影兽,該 GC 過(guò)程發(fā)生在年輕代中揭斧。從分代算法中,我們知道,JVM 為了性能考慮讹开,通常將內(nèi)存區(qū)域根據(jù)對(duì)象生命周期的不同分為年輕代和年老代盅视。

新創(chuàng)建的對(duì)象基本上都存放在年輕代(除了一些大對(duì)象),因?yàn)榇蠖鄶?shù)對(duì)象都是很快變成引用不可達(dá)旦万,所以大多數(shù)對(duì)象都在年輕代中創(chuàng)建闹击,然后消失。當(dāng)對(duì)象從這塊內(nèi)存區(qū)域消失時(shí)成艘,我們稱之為 YGC赏半。

什么時(shí)候發(fā)生 YGC 呢?當(dāng) Eden 不夠放入新創(chuàng)建的對(duì)象時(shí)淆两,也就是Eden 區(qū)滿了断箫,JVM 就會(huì)清理Eden 區(qū)的空間,將存活的對(duì)象放入 to 區(qū)秋冰,如果 to 區(qū)放不下仲义,則直接進(jìn)入老年代。如果 to 區(qū)能放下剑勾,則放入 to 區(qū)埃撵,然后清理掉無(wú)用對(duì)象,第二次 YGC 時(shí)虽另,GC 掃描 Eden 區(qū)和 to 區(qū)暂刘,將這兩個(gè)區(qū)的存活對(duì)象放入到 from 區(qū),將 to 區(qū)清空(總之一定會(huì)保證有一個(gè) Survivor 區(qū)是干凈的)捂刺,同樣的谣拣,如果 from 區(qū)放不下,則通過(guò)分配擔(dān)保機(jī)制進(jìn)入老年代叠萍。如果 YGC 后芝发,仍放不下新對(duì)象,則也通過(guò)分配擔(dān)保進(jìn)入老年代苛谷。

2. Old GC

通常辅鲸,我們將 Old GC 等同于 Full GC,為什么呢腹殿?我們?cè)敿?xì)解釋一下独悴。

什么時(shí)候發(fā)生 Old GC? 當(dāng)老年代空間滿了的時(shí)候锣尉。也就是說(shuō)通常是 YGC 后有很多對(duì)象進(jìn)入到老年代刻炒,而老年代無(wú)法放下這些對(duì)象,這時(shí)候就需要對(duì)老年代 GC自沧。而通常的 Old GC 其實(shí)就是 Full GC 坟奥。

3. Full GC

也就是全 GC 树瞭,對(duì)整個(gè)堆和方法區(qū)(如果存在)進(jìn)行 GC。
哪些情況會(huì) Full GC 呢爱谁?

  1. System.gc() 方法的調(diào)用
  2. heap dump 帶 GC
  3. 永久代(方法區(qū))空間不夠
  4. 當(dāng)準(zhǔn)備出發(fā) YGC 時(shí)晒喷,發(fā)現(xiàn)之前 YGC 后晉升對(duì)象的大小比目前 Old 區(qū)的剩余空間大,則不會(huì)觸發(fā) YGC 访敌,轉(zhuǎn)而直接觸發(fā) Full GC凉敲。

第四條說(shuō)到晉升,什么是晉升呢寺旺?YGC 后爷抓,幸存的對(duì)象會(huì)放入到 Survivor 區(qū),如果一個(gè)對(duì)象在多次 YGC 后仍然存活阻塑,則進(jìn)入老年代蓝撇,這個(gè)過(guò)程叫做晉升。每次 YGC 后叮姑,這個(gè)對(duì)象的年齡加一唉地。當(dāng)然,晉升的條件比較復(fù)雜传透。我們后面會(huì)詳細(xì)講述。

4. Mixed GC

G1 專屬GC极颓,這里不準(zhǔn)備講述這個(gè) GC朱盐。

總結(jié)

到這里,我們解釋了3種垃圾回收算法菠隆,第四個(gè)不算是算法兵琳,而是一種設(shè)計(jì)。還大致講了5種收集器骇径,并將這個(gè)坑留在了后面的文章里躯肌,最后講了一些 GC 術(shù)語(yǔ),YGC 破衔,Old GC 清女,F(xiàn)ull GC 等。

好了晰筛,關(guān)于5種垃圾收集器的詳細(xì)介紹嫡丙,我們將在 深入淺出 JVM GC(3)中詳細(xì)說(shuō)明。

good luck6恋凇J锊!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末怜瞒,一起剝皮案震驚了整個(gè)濱河市父泳,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖惠窄,帶你破解...
    沈念sama閱讀 210,914評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件逝她,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡睬捶,警方通過(guò)查閱死者的電腦和手機(jī)黔宛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評(píng)論 2 383
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)擒贸,“玉大人臀晃,你說(shuō)我怎么就攤上這事〗榻伲” “怎么了徽惋?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,531評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)座韵。 經(jīng)常有香客問(wèn)我险绘,道長(zhǎng),這世上最難降的妖魔是什么誉碴? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,309評(píng)論 1 282
  • 正文 為了忘掉前任宦棺,我火速辦了婚禮,結(jié)果婚禮上黔帕,老公的妹妹穿的比我還像新娘代咸。我一直安慰自己,他們只是感情好成黄,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布呐芥。 她就那樣靜靜地躺著,像睡著了一般奋岁。 火紅的嫁衣襯著肌膚如雪思瘟。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,730評(píng)論 1 289
  • 那天闻伶,我揣著相機(jī)與錄音滨攻,去河邊找鬼。 笑死虾攻,一個(gè)胖子當(dāng)著我的面吹牛铡买,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播霎箍,決...
    沈念sama閱讀 38,882評(píng)論 3 404
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼奇钞,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了漂坏?” 一聲冷哼從身側(cè)響起景埃,我...
    開(kāi)封第一講書(shū)人閱讀 37,643評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤媒至,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后谷徙,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體拒啰,經(jīng)...
    沈念sama閱讀 44,095評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評(píng)論 2 325
  • 正文 我和宋清朗相戀三年完慧,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了谋旦。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,566評(píng)論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡屈尼,死狀恐怖册着,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情脾歧,我是刑警寧澤甲捏,帶...
    沈念sama閱讀 34,253評(píng)論 4 328
  • 正文 年R本政府宣布,位于F島的核電站鞭执,受9級(jí)特大地震影響司顿,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜兄纺,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評(píng)論 3 312
  • 文/蒙蒙 一大溜、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧囤热,春花似錦猎提、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,715評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)疙教。三九已至棺聊,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間贞谓,已是汗流浹背限佩。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,945評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留裸弦,地道東北人祟同。 一個(gè)月前我還...
    沈念sama閱讀 46,248評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像理疙,于是被迫代替她去往敵國(guó)和親晕城。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評(píng)論 2 348

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

  • JVM架構(gòu) 當(dāng)一個(gè)程序啟動(dòng)之前窖贤,它的class會(huì)被類裝載器裝入方法區(qū)(Permanent區(qū))砖顷,執(zhí)行引擎讀取方法區(qū)的...
    cocohaifang閱讀 1,648評(píng)論 0 7
  • 原文閱讀 前言 這段時(shí)間懈怠了贰锁,罪過(guò)! 最近看到有同事也開(kāi)始用上了微信公眾號(hào)寫(xiě)博客了滤蝠,挺好的~給他們點(diǎn)贊豌熄,這博客我...
    碼農(nóng)戲碼閱讀 5,952評(píng)論 2 31
  • 聲明:原創(chuàng)文章,轉(zhuǎn)載請(qǐng)注明出處物咳。http://www.reibang.com/u/e02df63eaa87 垃圾收...
    唐影若凡閱讀 1,055評(píng)論 1 6
  • 一. 垃圾回收的意義 在C++中锣险,對(duì)象所占的內(nèi)存在程序結(jié)束運(yùn)行之前一直被占用,在明確釋放之前不能分配給其它對(duì)...
    Stan_Z閱讀 1,924評(píng)論 0 25
  • 1.什么是垃圾回收览闰? 垃圾回收(Garbage Collection)是Java虛擬機(jī)(JVM)垃圾回收器提供...
    簡(jiǎn)欲明心閱讀 89,446評(píng)論 17 311