GC的收集器&回收算法

收集器

  1. Serial收集器
    單線程的收集器(只會(huì)使用一個(gè)CPU或一條收集線程去完成垃圾收集工作,進(jìn)行垃圾收集時(shí),必須暫停其他所有的工作線程,直到它收集結(jié)束。)

虛擬機(jī)運(yùn)行在<code>Client</code>模式下的默認(rèn)新生代收集器。與其他收集器的單線程比更加簡(jiǎn)單高效。

Serial收集器工作過(guò)程
  1. ParNew收集器
    Serial收集器的多線程版本
    運(yùn)行在<code>Server</code>模式下的虛擬機(jī)中首選的新生代收集器。其中一個(gè)與性能無(wú)關(guān)但很重要的原因是,除了Serial收集器外,目前只有它能與CMS收集器配合工作。
ParNew收集器工作過(guò)程
  1. Parallel Scavenge收集器
    它的關(guān)注點(diǎn)與其他收集器不同,CMS等收集器的關(guān)注點(diǎn)是盡可能縮短垃圾收集時(shí)用戶線程停頓時(shí)間,而Parallel Scavenge收集器的目標(biāo)則是達(dá)到一個(gè)可控制的吞吐量

吞吐量=運(yùn)行用戶代碼時(shí)間/(運(yùn)行用戶代碼時(shí)間+垃圾收集時(shí)間)

  1. Serial Old收集器
    Serial收集器的老年代版本,單線程收集器,使用“標(biāo)記-整理”算法。

  2. Parallel Old收集器
    Parallel Scavenge收集器的老年代版本,使用多線程,基于“標(biāo)記-整理”算法。(JDK1.6中才開(kāi)始提供)

  1. CMS收集器(Concurrent Mark Sweep)
    以獲取最短回收停頓時(shí)間為目的的收集器,基于“標(biāo)記-清除”算法。
CMS運(yùn)作步驟

耗時(shí)最長(zhǎng)的并發(fā)標(biāo)記并發(fā)清除過(guò)程收集器線程都可以與用戶線程一起工作。所以,CMS收集器的內(nèi)存回收過(guò)程是與用戶線程一起并發(fā)執(zhí)行的。

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

  • 并發(fā)收集
  • 低停頓

缺點(diǎn):

  • CMS收集器對(duì)CPU資源非常敏感。 在并發(fā)階段,它雖然不會(huì)導(dǎo)致用戶線程停頓,但是會(huì)因?yàn)檎加靡徊糠志€程(或者說(shuō)CPU資源)而導(dǎo)致應(yīng)用程序變慢,總吞吐量會(huì)降低。
  • CMS收集器無(wú)法處理浮動(dòng)垃圾,可能出現(xiàn)Concurrent Mode Failure失敗而導(dǎo)致另一次Full GC產(chǎn)生。由于CMS并發(fā)清理階段用戶線程還在運(yùn)行著,伴隨程序運(yùn)行自然就還會(huì)有新的垃圾不斷產(chǎn)生,這一部分垃圾出現(xiàn)在標(biāo)記過(guò)程之后,CMS無(wú)法再當(dāng)次收集中處理掉它們,治好留待下一次GC時(shí)再清理掉。這部分垃圾就稱為“浮動(dòng)垃圾”。因此,CMS不能像其他收集器那樣等到老年代幾乎完全被填滿再進(jìn)行手機(jī),CMS需要預(yù)留一部分空間。
  • 由于CMS基于“標(biāo)記-清除”算法,意味著收集結(jié)束時(shí)會(huì)有大量空間碎片產(chǎn)生。
  1. G1 收集器
    當(dāng)今收集器技術(shù)發(fā)展的最前沿成果之一,G1是面向服務(wù)端應(yīng)用的垃圾收集器。

特點(diǎn)

  • 并行與并發(fā):充分利用多CPU、多核環(huán)境下的硬件優(yōu)勢(shì),使用多個(gè)CPU(CPU或CPU核心)來(lái)縮短Stop-The-World停頓時(shí)間。部分其他收集器需要停頓Java線程執(zhí)行的GC動(dòng)作,G1仍然能通過(guò)并發(fā)方式讓Java程序繼續(xù)執(zhí)行。
  • 分代收集:與其他收集器一樣,分代概念在G1中依然得以保存。
  • 空間整合:與CMS的“標(biāo)記-清理”算法不同,G1從整體上看是基于<code>“標(biāo)記-整理”算法</code>實(shí)現(xiàn)的收集器,從局部上看是基于<code>“復(fù)制”算法</code>實(shí)現(xiàn)的,這兩種算法意味著G1運(yùn)作期間不會(huì)產(chǎn)生內(nèi)存空間碎片。
  • 可預(yù)測(cè)的停頓:這是G1相對(duì)于CMS的另一大優(yōu)勢(shì),降低停頓時(shí)間是G1和CMS共同關(guān)注點(diǎn),但G1除了追求低停頓外,還能建立可預(yù)測(cè)的停頓時(shí)間模型,能讓使用者明確指定一個(gè)長(zhǎng)度為M毫秒的時(shí)間片段內(nèi),消耗在垃圾收集上的時(shí)間不得從超出N毫秒,這幾乎已經(jīng)是實(shí)時(shí)Java的垃圾收集器的特征了。

回收算法

  1. 標(biāo)記 - 清除



    分為“標(biāo)記”和“清除”兩個(gè)階段,首先標(biāo)記出所有需要回收的對(duì)象,在標(biāo)記完成后統(tǒng)一回收所有被標(biāo)記的對(duì)象。

缺點(diǎn):

  • 標(biāo)記和清除兩個(gè)過(guò)程效率不高
  • 標(biāo)記清除后產(chǎn)生大量不連續(xù)的內(nèi)存碎片。
  1. 標(biāo)記 - 整理


讓所有存活對(duì)象向一端移動(dòng)。

  1. 復(fù)制算法

將內(nèi)存分為兩部分,每次使用其中一塊,當(dāng)這塊內(nèi)存用完,就將還存活的對(duì)象復(fù)制到另一塊上面。

缺點(diǎn):

  • 浪費(fèi)一半內(nèi)存(改進(jìn)的方法是將新生代分為Eden、From Survivor、To Survivor。)
  1. 分代收集算法


把對(duì)象按照壽命長(zhǎng)短進(jìn)行分組,分為新生代和老年代,然后根據(jù)各個(gè)年代的特點(diǎn)采用最適當(dāng)?shù)氖占惴ǎ谛律捎脧?fù)制算法,在老年代采用“標(biāo)記-清除”或者“標(biāo)記-整理”算法。


搜索算法

  1. 引用計(jì)數(shù)算法(已廢棄)
    給對(duì)象添加一個(gè)引用計(jì)數(shù)器,每當(dāng)有一個(gè)地方引用它時(shí),計(jì)數(shù)器+1,引用失效計(jì)數(shù)器-1;任何時(shí)候計(jì)數(shù)器為0的對(duì)象就是不可能再被使用。這有個(gè)問(wèn)題是,兩個(gè)對(duì)象相互引用導(dǎo)致兩個(gè)對(duì)象都無(wú)法被回收。

  2. 可達(dá)性分析算法
    通過(guò)一系列的GC Roots對(duì)象作為起點(diǎn),從這些節(jié)點(diǎn)開(kāi)始向下搜索。搜索所走過(guò)的路稱為引用鏈。當(dāng)一個(gè)對(duì)象到GC Roots沒(méi)有任何引用鏈相連時(shí),則證明此對(duì)象不可用。

可作為GC Root的對(duì)象有:

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

即使在可達(dá)性分析中不可達(dá)的對(duì)象,也并非是“非死不可”,這時(shí)候他們暫時(shí)處于“緩刑”階段。要真正宣告一個(gè)對(duì)象死亡,需要經(jīng)歷兩個(gè)階段:
1)如果對(duì)象在進(jìn)行可達(dá)性分析后發(fā)現(xiàn)沒(méi)有與GC Roots相連接的引用鏈,那它會(huì)被第一次標(biāo)記并且進(jìn)行一次篩選,篩選的條件是此對(duì)象是否有必要執(zhí)行finalize()方法。當(dāng)對(duì)象沒(méi)有覆蓋finalize()方法,或者finalize()方法已經(jīng)被虛擬機(jī)調(diào)用過(guò),虛擬機(jī)將這兩種情況都視為“沒(méi)有必要執(zhí)行”。

2)如果這個(gè)對(duì)象唄判斷為有必要執(zhí)行finalize()方法。那么這個(gè)對(duì)象會(huì)被放到一個(gè)F-Queue隊(duì)列中,并在稍后由一個(gè)虛擬機(jī)自動(dòng)建立的、優(yōu)先級(jí)低的Finalizer線程去執(zhí)行它,這里的“執(zhí)行”是指虛擬機(jī)會(huì)觸發(fā)這個(gè)方法,但并不承諾等待它運(yùn)行結(jié)束。這是為了防止finalize()方法執(zhí)行緩慢使得F-Queue隊(duì)列其他對(duì)象永久等待。
因此,對(duì)象可以在finalize()方法里把自己賦值給一個(gè)變量,以達(dá)到“自救”的目的,但是這樣的“自救”只能用一次(虛擬機(jī)只會(huì)調(diào)用一次finalize()方法)。


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容