JVM—【02】認(rèn)識(shí)JVM的垃圾回收算法與收集器

1. 對(duì)象存活判斷

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

  • 給對(duì)象添加一個(gè)引用計(jì)數(shù)器砾省,每當(dāng)有一個(gè)地方引用它的時(shí)候,計(jì)數(shù)器值就加一沸手;當(dāng)引用失效時(shí)内边,計(jì)數(shù)器值就減一;任何時(shí)刻計(jì)數(shù)器為0的對(duì)象就是不可能再被使用的索绪。
  • 主流的JVM沒有選用引用計(jì)數(shù)算法來管理內(nèi)存湖员,主要的原因是它很難解決對(duì)象之間的相互循環(huán)引用的問題。

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

  • 通過一系列稱為“GC-Roots”的對(duì)象作為起點(diǎn)瑞驱,從這些結(jié)點(diǎn)開始向下搜索娘摔,搜索所走過的路徑稱為引用鏈(Reference Chain),當(dāng)一個(gè)對(duì)象到GC Roots沒有任何引用鏈相連時(shí)唤反,則證明此對(duì)象是不可用的(圖論中的不可達(dá))凳寺。
  • 可作為GC Roots的對(duì)象:

虛擬機(jī)棧(戰(zhàn)爭(zhēng)中的本地變量表)中引用的對(duì)象

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

方法區(qū)中常量引用的對(duì)象

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


1.3. 引用類型 Reference

  • 強(qiáng)引用:Strong Reference

指的是類似于Object object = new Object()這類引用,只要強(qiáng)引用存在彤侍,垃圾收集器就永遠(yuǎn)不會(huì)回收被引用對(duì)象肠缨。

  • 軟引用:Soft Reference

描述一些還有用但并非必要的對(duì)象。JDK提供了SoftReference來實(shí)現(xiàn)軟引用

在系統(tǒng)快要發(fā)生內(nèi)存溢出之前盏阶,將會(huì)把這些對(duì)象列進(jìn)回收范圍之中進(jìn)行第二次回收晒奕。如果這次回收還沒有足夠的內(nèi)存,才會(huì)拋出內(nèi)存溢出異常名斟。

  • 弱引用: Weak Reference

用來描述非必須對(duì)象脑慧,它的強(qiáng)度比軟引用更弱一些,被弱引用關(guān)聯(lián)的對(duì)象只能生存到下一次垃圾收集發(fā)生之前砰盐。JDK提供了WeakReference類來實(shí)現(xiàn)弱引用闷袒。

當(dāng)垃圾收集器工作時(shí),無論當(dāng)前內(nèi)存是否足夠楞卡,都會(huì)回收掉只被弱引用關(guān)聯(lián)的對(duì)象霜运。

  • 虛引用:Phantom Reference

也稱為幽靈引用或幻影引用脾歇,它是最弱的一種引用關(guān)系。一個(gè)對(duì)象是否有虛引用的存在淘捡,完全不會(huì)對(duì)其生存時(shí)間構(gòu)成影響藕各,也無法通過虛引用來取得一個(gè)對(duì)象實(shí)例。JDK提供PhantomReference類來實(shí)現(xiàn)虛引用

為一個(gè)對(duì)象設(shè)置虛引用關(guān)聯(lián)的唯一目的就是能在這個(gè)對(duì)象被收集器回收時(shí)收到一個(gè)系統(tǒng)通知焦除。


1.3. 引用類型 Reference

  • 不可達(dá)對(duì)象激况,會(huì)暫時(shí)處于“緩刑”階段,要真正宣告一個(gè)對(duì)象死亡,至少要經(jīng)歷兩次標(biāo)記過程:

    如果對(duì)象在進(jìn)行可達(dá)性分析后發(fā)現(xiàn)沒有與GC Roots相連接的引用鏈,那它將會(huì)被第一次標(biāo)記并且進(jìn)行一次篩選,篩選的條件是此對(duì)象是否有必要執(zhí)行finalize()方法當(dāng)對(duì)象沒有覆蓋finalize()方法,或者finalize()方法已經(jīng)被虛擬機(jī)調(diào)用過,虛擬機(jī)將這兩種情況都視為“沒有必要執(zhí)行”膘魄。

    finalize()方法是對(duì)象逃脫死亡命運(yùn)的最后一次機(jī)會(huì),稍后GC將對(duì)F-Queue中的對(duì)象進(jìn)行第二次小規(guī)模的標(biāo)記,如果對(duì)象要在finalize()中成功拯救自己——只要重新與引用鏈上的任何一個(gè)對(duì)象建立關(guān)聯(lián)即可,譬如把自己(this關(guān)鍵字)賦值給某個(gè)類變量或者對(duì)象的成員變量,那在第二次標(biāo)記時(shí)它將被移除出“即將回收”的集合;如果對(duì)象這時(shí)候還沒有逃脫,那基本上它就真的被回收了乌逐。

    注:如果對(duì)象唄判定有必要執(zhí)行finalize()方法,那么這個(gè)對(duì)象將會(huì)放置在一個(gè)叫做F-Queue隊(duì)列中创葡,并隨后JVM會(huì)創(chuàng)建一個(gè)低優(yōu)先級(jí)的Finalizer線程去執(zhí)行它浙踢。JVM觸發(fā)這個(gè)方法,并不確保它會(huì)執(zhí)行結(jié)束灿渴,因?yàn)槿绻麑?duì)象finalize方法如果執(zhí)行緩慢或者死循環(huán)洛波,將很有可能會(huì)導(dǎo)致F-Queue隊(duì)列其他對(duì)象永久等待,甚至導(dǎo)致整個(gè)內(nèi)存回收系統(tǒng)奔潰骚露。


2. 垃圾收集算

2.1. 標(biāo)記-清除算法 Mark-Sweep

  • 算法分兩個(gè)階段蹬挤,即標(biāo)記和清除。

    1. 標(biāo)記處所需要回收的對(duì)象
    1. 標(biāo)記完成后統(tǒng)一回收所有被標(biāo)記對(duì)象
  • 算法主要不足

    1. 效率問題棘幸,標(biāo)記和清除兩個(gè)過程效率都不高
    2. 空間問題焰扳,標(biāo)記清除后悔產(chǎn)生大量不連續(xù)的空間

    空間碎片太多可能會(huì)導(dǎo)致以后分配大對(duì)象時(shí)無法找到足夠連續(xù)內(nèi)存存放而不得不觸發(fā)另一次垃圾收集。


2.2. 復(fù)制算法 Copying

  • 將可用的內(nèi)存按照容量劃分為大小相等的兩塊误续,每次使用其中一塊吨悍。當(dāng)前一塊用完了,將還存活的對(duì)象移動(dòng)到另一塊上面女嘲,然后把已使用過的內(nèi)存空間一次性清理掉畜份。這樣每次都是堆整個(gè)半?yún)^(qū)進(jìn)行內(nèi)存回收,分配內(nèi)存時(shí)也就不考慮內(nèi)存碎片等復(fù)雜情況欣尼,實(shí)現(xiàn)簡(jiǎn)單、運(yùn)行高效停蕉。代價(jià)是將內(nèi)存縮小為原來的一半愕鼓。

2.3. 標(biāo)記-整理算法 Mark-Compact

  • 標(biāo)記后不直接對(duì)可回收對(duì)象清理,而是讓所有存活的對(duì)象都向一端移動(dòng)慧起,然后直接清理掉端邊界以為的內(nèi)存菇晃。

2.4. 分代收集算法 Generational Collection

  • 把JVM堆內(nèi)存分為新生代和老年代,對(duì)不同的年代采取不同的收集算法蚓挤。

    在新生代中每次垃圾收集時(shí)都發(fā)現(xiàn)有大批對(duì)象死去磺送,只有少量存活驻子,那就選用復(fù)制算法。

    老年代中因?yàn)閷?duì)象存活率高估灿、沒有額外空間對(duì)它進(jìn)行分配擔(dān)保崇呵,那就必須使用“標(biāo)記-清理”或“標(biāo)記-整理”算法來進(jìn)行回收。


3. 垃圾收集算

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

  • 可達(dá)性分析從GC Roots節(jié)點(diǎn)找引用鏈操作馅袁,現(xiàn)在引用僅方法區(qū)就有數(shù)百兆域慷,逐個(gè)檢查里面的引用非常耗時(shí)。
  • 可達(dá)性分析對(duì)執(zhí)行時(shí)間的敏感上體現(xiàn)在GC停頓上汗销,這項(xiàng)分析工作必須在一個(gè)能確保一致性的快照中犹褒,

    這里的一致性是指在整個(gè)分析期間整個(gè)執(zhí)行系統(tǒng)開起來像被凍結(jié)在某個(gè)時(shí)間節(jié)點(diǎn)上。如果這點(diǎn)不滿足準(zhǔn)確性就無法保證弛针。這是導(dǎo)致GC進(jìn)行時(shí)必須停頓所有Java執(zhí)行線程的其中一個(gè)重要原因叠骑。即使在CMS收集器(號(hào)稱幾乎不發(fā)生停頓)中枚舉根節(jié)點(diǎn)也是必須要停頓的。

  • 主流的JVM都是使用的準(zhǔn)確式GC削茁,所以當(dāng)執(zhí)行系統(tǒng)停頓下來并不需要一個(gè)不漏檢查完所有執(zhí)行上下文和全局的引用位置宙枷,JVM知道哪里存放這個(gè)信息,在HotSpot使用了一組OopMap的數(shù)據(jù)結(jié)構(gòu)來達(dá)到這個(gè)目的付材。

    在類加載完后朦拖,HotSpot吧對(duì)象內(nèi)的各個(gè)偏移量上的類型計(jì)算出來,在JIT編譯過程中厌衔,也會(huì)在特定的位置記錄下棧和寄存器中哪些位置是引用璧帝。在GC掃描時(shí),就可以直接知道這些信息富寿。


3.2. 安全點(diǎn) Safepoint

  • HotSpot在特定的位置記錄棧和寄存器中哪些位置是引用睬隶,這個(gè)“特定位置”就稱為“安全點(diǎn)”,即程序執(zhí)行時(shí)并非在所有地方都能停頓下來開始GC页徐,只有在到達(dá)安全點(diǎn)時(shí)才能暫停苏潜。

  • 安全點(diǎn)不能太多,也不能太少变勇,太多增大系統(tǒng)負(fù)荷恤左,太少GC等待時(shí)間太長(zhǎng)。所以安全點(diǎn)的選擇基本是以“是否具有讓程序長(zhǎng)時(shí)間執(zhí)行的特征”為標(biāo)準(zhǔn)選定搀绣。

    因?yàn)槊織l指令執(zhí)行時(shí)間都非常短暫飞袋,程序不太可能因?yàn)橹噶盍鏖L(zhǎng)度太長(zhǎng)而過長(zhǎng)時(shí)間運(yùn)行,所以長(zhǎng)時(shí)間的特征就是指令序列復(fù)用链患、循環(huán)跳轉(zhuǎn)巧鸭、異常跳轉(zhuǎn)

  • 怎樣確保GC發(fā)生所有線程都跑到安全點(diǎn)再停頓下來,有兩種方案:

    搶先式中斷(Preemptive Suspension):在發(fā)生GC時(shí)麻捻,首先把所有線程全部中斷纲仍,如果發(fā)現(xiàn)有線程中斷的地方不在安全點(diǎn)上呀袱,就恢復(fù)線程,讓它跑到安全點(diǎn)上郑叠。

    主動(dòng)式中斷(Voluntary Suspension):當(dāng)GC需要中斷線程時(shí)夜赵,不對(duì)線程直接操作,僅簡(jiǎn)單設(shè)置一個(gè)標(biāo)志锻拘,各個(gè)線程執(zhí)行時(shí)主動(dòng)去輪詢這個(gè)標(biāo)志油吭,發(fā)現(xiàn)中斷標(biāo)志為真的時(shí)候就自己把中斷掛起。輪詢標(biāo)志這個(gè)地方和安全點(diǎn)是重合的署拟,另外再加上創(chuàng)建對(duì)象需要分配內(nèi)存的地方婉宰。


3.3. 安全區(qū)域 Safe Region

  • 安全區(qū)域是指一段代碼片段中,引用關(guān)系不會(huì)發(fā)發(fā)生變化推穷。在這個(gè)區(qū)域中的任意地方開始GC都是安全的心包。
  • 在線程執(zhí)行到Safe Region中的代碼時(shí),首先表示自己進(jìn)入了Safe Region馒铃,這這段時(shí)間里蟹腾,JVM要發(fā)起GC時(shí),就不用管標(biāo)識(shí)自己為Safe Region狀態(tài)的線程了区宇。在線程要離開Safe Region時(shí)娃殖,它要檢查系統(tǒng)是否已經(jīng)完成了根節(jié)點(diǎn)枚舉(或者整個(gè)GC過程),如果完成了议谷,那線程就繼續(xù)執(zhí)行炉爆,否則它就必須等待知道收到可以安全離開Safe Region的信號(hào)為止。

4. 垃圾收集器

4.1. Serial收集器

  • 是一個(gè)單線程垃圾收集器卧晓,它只會(huì)使用一個(gè)CPU或者一條收集線程去完成垃圾收集工作芬首。
  • 它在進(jìn)行垃圾收集時(shí),必須暫停其他所有的工作線程逼裆,知道收集結(jié)束郁稍。
  • 適用于Client。
  • 新生代使用復(fù)制算法胜宇,暫停所有線程耀怜;老年代使用標(biāo)記-整理算法,暫停所有線程桐愉。

4.2. ParNew收集器

  • Serial的多線程版本封寞,除了使用多條線程進(jìn)行垃圾收集之外,其余行為包括Serial收集器的可用參數(shù)仅财、收集算法、Stop The World碗淌、對(duì)象分配規(guī)則盏求、回收策略都與Serial收集器完全一樣

  • 除了Serial收集器外抖锥,目前只有它能與CMS收集器配合工作。

    ParNew收集器也是使用-XX:+UseConcMarkSweepGC選項(xiàng)后的默認(rèn)新生代收集器碎罚,也可以使用-XX:+UseParNewGC選項(xiàng)強(qiáng)制指定磅废。

    ParNew在單核下不會(huì)比Serial收集器效果好

    可以使用-XX:ParallelGCThreads參數(shù)來限制垃圾收集的線程數(shù)。


4.3. Parallel Scavenge收集器

  • 他是一個(gè)新生代處理器荆烈,也是使用復(fù)制算法的收集器拯勉,也是并行的多線程處理器。

  • Parallel Scavenge收集器的目的是達(dá)到一個(gè)可控制的吞吐量憔购。

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

  • 它提供了兩個(gè)參數(shù)控制吞吐量:控制最大垃圾收集停頓的時(shí)間-XX:MaxGCPauseMillis宫峦,直接設(shè)置吞吐量大小-XX:GCTimeRatio

    -XX:MaxGCPauseMillis:允許的值是一個(gè)大于0的毫秒數(shù),收集器將盡可能地保證內(nèi)存回收花費(fèi)不超過設(shè)定值玫鸟,GC停頓時(shí)間縮短是以犧牲吞吐量和新生代空間來換取的导绷。

    -XX:GCTimeRatio:參數(shù)的值是大于0小于100的整數(shù),就是垃圾收集時(shí)間占總時(shí)間的比率屎飘,如:19妥曲,允許最大的時(shí)間就是1/(1+19);99钦购,允許最大的時(shí)間就是1/(1+99)

  • Parallel Scavenge參數(shù):-XX:UseAdaptiveSizePolicy

    -XX:UseAdaptiveSizePolicy 打開這個(gè)參數(shù)檐盟,就不需要手工指定新生代大小、Eden與Survivor區(qū)的比列押桃、晉升老年代對(duì)象大小等細(xì)節(jié)參數(shù)葵萎。虛擬機(jī)會(huì)根據(jù)當(dāng)前系統(tǒng)的運(yùn)行情況收集性能監(jiān)控,動(dòng)態(tài)調(diào)整這些參數(shù)以提供最適合的停頓時(shí)間和最大吞吐量怨规,這種調(diào)節(jié)方式稱為GC自適應(yīng)調(diào)整策略(GC Ergonomics)


4.4. Serial Old收集器

  • Serial收集器的老年代版陌宿,單線程,使用“標(biāo)記-整理”算法
  • 作為CMS收集器的后背元波丰,在并發(fā)收集發(fā)生Concurrent Mode Failure時(shí)使用壳坪。

4.5. Parallel Old收集器

  • 是Parallel Scavenge收集器的老年代版本。使用多線程和“標(biāo)記-整理”算法掰烟。
  • 在注重吞吐量以及CPU資源敏感的場(chǎng)景爽蝴,可以優(yōu)先考慮Paralled Scavenge+Parallel Old收集器。

4.6 CMS(Concurrent Mark Swap) 收集器

  • CMS(Concurrent Mark Sweep)收集器是一種以獲取最短回收停頓時(shí)間為目標(biāo)的收集器纫骑。適用于互聯(lián)網(wǎng)站和B/S系統(tǒng)的服務(wù)端上蝎亚。并發(fā)收集、低停頓先馆。

  • CMS收集器是基于“標(biāo)記-清除”算法實(shí)現(xiàn)发框,過程分為4步:

    初始標(biāo)記(CMS initial mark):僅僅是標(biāo)記一下GC Roots能直接關(guān)聯(lián)到的對(duì)象,速度很快煤墙。

    并發(fā)標(biāo)記(CMS concurrent mark):進(jìn)行GC Roots Tracing的過程梅惯。

    重新標(biāo)記(CMS remark):是為了修正并發(fā)標(biāo)記期間因用戶程序繼續(xù)運(yùn)作而導(dǎo)致標(biāo)記產(chǎn)生變動(dòng)的那一部分對(duì)象的標(biāo)記記錄宪拥。停頓時(shí)間一般比初始標(biāo)記更長(zhǎng),遠(yuǎn)比并發(fā)標(biāo)記時(shí)間短铣减。

    并發(fā)清除(CMS concurrent sweep)

    其中初始標(biāo)記她君、重新標(biāo)記這兩個(gè)步驟仍然需要“stop the world”

  • CMS的幾個(gè)缺點(diǎn):

    對(duì)CPU資源非常敏感:它雖然不會(huì)導(dǎo)致用戶線程停頓,但是啟用線程葫哗,消耗CPU運(yùn)算資源缔刹,會(huì)導(dǎo)致引用程序變慢,總吞吐量降低劣针。CMS的默認(rèn)啟用回收的線程數(shù)是(CPU數(shù)量 + 3)/ 4.也就是說校镐,CPU越少,占用性能越多酿秸,對(duì)程序的影響就越大灭翔。為了應(yīng)對(duì)這種狀況,JVM提供了“增量式并發(fā)收集器”(Incremental Concurrent Mark Swap/i-CMS)辣苏,使用搶占式來模擬多任務(wù)機(jī)制肝箱,在并發(fā)標(biāo)記和清理的時(shí)候讓GC線程、用戶線程交替運(yùn)行稀蟋。盡量減少GC線程獨(dú)占資源的時(shí)間煌张,這樣整個(gè)垃圾收集時(shí)間過程會(huì)更長(zhǎng),但是對(duì)用戶的影響就顯得更少退客。

    CMS無法處理“浮動(dòng)垃圾(Floating Garbage)”骏融,可能出現(xiàn)“Concurrent Mode Failure”失敗而導(dǎo)致另一次Full GC的產(chǎn)生。浮動(dòng)垃圾即在CMS并發(fā)清理時(shí)用戶線程還在運(yùn)行產(chǎn)生的心垃圾萌狂,這部分垃圾出現(xiàn)在標(biāo)記過后档玻,無法再當(dāng)次處理。正因?yàn)橛脩艟€程還在運(yùn)行茫藏,就需要預(yù)留一部分內(nèi)存給用戶線程使用误趴,所以CMS可以設(shè)置觸發(fā)百分比:-XX:CMSInitiatingOccupancyFraction=70-XX:+UseCMSInitiatingOccupancyOnly 前者設(shè)置百分比,后者設(shè)置只用設(shè)置的百分比务傲,不讓JVM自動(dòng)調(diào)整凉当,如果不設(shè)置后面的,第一次會(huì)使用70售葡,隨后就會(huì)隨JVM自動(dòng)調(diào)整了看杭。如果CMS運(yùn)行時(shí),預(yù)留內(nèi)存無法滿足需要挟伙,就會(huì)出現(xiàn)“Concurrent Mode Failure”楼雹,這是JVM就會(huì)啟用后后備方案使用Serial Old來重新進(jìn)行老年代收集。所以比例不能設(shè)置太高,不然就會(huì)容易引起Concurrent Mode Failure烘豹,性能反而降低瓜贾。

    CMS是基于“標(biāo)記-清除”算法實(shí)現(xiàn)的,所以收集結(jié)束后會(huì)有大量的空間碎片產(chǎn)生携悯。雖然空間很多,但是無法給大對(duì)象找到一片連續(xù)的空間筷笨,從而不得不觸發(fā)一次Full GC。為了解決這個(gè)問題,CMS提供了一個(gè)-XX:+UseCMSCompactAtFullCollection,用于在CMS要進(jìn)行Full GC的時(shí)候開啟內(nèi)存碎片合并整理炒嘲,這個(gè)過程無法并發(fā)進(jìn)行越平,空間碎片問題解決,但是停頓時(shí)間變長(zhǎng)仰禀。CMS還有一個(gè)-XX:CMSFullGCsBeforeCompaction照雁,這個(gè)參數(shù)是用于設(shè)置執(zhí)行多少次不壓縮的Full GC后,跟著來一次帶壓縮的答恶,為0是表示每次進(jìn)入Full GC 都?jí)嚎s饺蚊。


4.7 G1(Garbage-First)收集器

  • G1是一款面向服務(wù)端應(yīng)用的垃圾收集器。HotSpot開發(fā)來替代CMS的悬嗓,特點(diǎn)如下:

    并行與并發(fā): G1能充分利用多CPU污呼、多核環(huán)境下的硬件優(yōu)勢(shì),使用多個(gè)CPU來縮短Stop-The-World停頓的時(shí)間包竹,部分其他收集器原本需要停頓Java線程執(zhí)行的GC動(dòng)作燕酷,G1收集器仍然可以通過并發(fā)的方式讓Java程序繼續(xù)執(zhí)行。

    分代收集: 分代概念在G1中依然得以保留周瞎。G1可以不需要其他收集器配合就能獨(dú)立管理整個(gè)GC堆苗缩,它能夠采用不同的方式去處理新創(chuàng)建的對(duì)象和已經(jīng)存活了一段時(shí)間、熬過多次GC的舊對(duì)象以獲取更好的收集效果声诸。G1可以自己管理新生代和老年代酱讶。

    可預(yù)測(cè)的停頓: 降低停頓時(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(RTSJ)的垃圾收集器的特征了软免。G1可以有計(jì)劃的避免在整個(gè)JVM堆中進(jìn)行垃圾收集,可以對(duì)每個(gè)region里的回收對(duì)象價(jià)值(回收該區(qū)域的時(shí)間消耗和能得到的內(nèi)存比值)進(jìn)行分析焚挠,在最后篩選回收階段膏萧,對(duì)每個(gè)region里的回收對(duì)象價(jià)值(回收該區(qū)域的時(shí)間消耗和能得到的內(nèi)存比值)最后進(jìn)行排序,用戶可以自定義停頓時(shí)間,那么G1就可以對(duì)部分的region進(jìn)行回收榛泛!這使得停頓時(shí)間是用戶自己可以控制的蝌蹂!

    空間整合,沒有內(nèi)存碎片產(chǎn)生:由于G1使用了獨(dú)立區(qū)域(Region)概念曹锨,G1從整體來看是基于“標(biāo)記-整理”算法實(shí)現(xiàn)收集孤个,從局部(兩個(gè)Region)上來看是基于“復(fù)制”算法實(shí)現(xiàn)的,但無論如何沛简,這兩種算法都意味著G1運(yùn)作期間不會(huì)產(chǎn)生內(nèi)存空間碎片齐鲤。

  • 在G1之前的其他收集器進(jìn)行收集的范圍都是整個(gè)新生代或者老年代,而G1不再是這樣椒楣。使用G1收集器時(shí)给郊,Java堆的內(nèi)存布局就與其他收集器有很大差別,它將整個(gè)Java堆劃分為多個(gè)大小相等的獨(dú)立區(qū)域(Region)捧灰,雖然還保留有新生代和老年代的概念淆九,但新生代和老年代不再是物理隔離的了,它們都是一部分Region(不需要連續(xù))的集合毛俏。

  • G1收集器之所以能建立可預(yù)測(cè)的停頓時(shí)間模型炭庙,是因?yàn)樗梢杂杏?jì)劃地避免在整個(gè)Java堆中進(jìn)行全區(qū)域的垃圾收集。G1跟蹤各個(gè)Region里面的垃圾堆積的價(jià)值大信《丁(回收所獲得的空間大小以及回收所需時(shí)間的經(jīng)驗(yàn)值)煤搜,在后臺(tái)維護(hù)一個(gè)優(yōu)先列表,每次根據(jù)允許的收集時(shí)間唧席,優(yōu)先回收價(jià)值最大的Region(這也就是Garbage-First名稱的來由)擦盾。這種使用Region劃分內(nèi)存空間以及有優(yōu)先級(jí)的區(qū)域回收方式,保證了G1收集器在有限的時(shí)間內(nèi)可以獲取盡可能高的收集效率淌哟。

  • G1收集器中迹卢,Region之間的對(duì)象引用以及其他收集器中的新生代與老年代之間的對(duì)象引用,虛擬機(jī)都是使用Remembered Set來避免全堆掃描的徒仓。G1中每個(gè)Region都有一個(gè)與之對(duì)應(yīng)的Remembered Set腐碱,虛擬機(jī)發(fā)現(xiàn)程序在對(duì)Reference類型的數(shù)據(jù)進(jìn)行寫操作時(shí),會(huì)產(chǎn)生一個(gè)Write Barrier暫時(shí)中斷寫操作掉弛,檢查Reference引用的對(duì)象是否處于不同的Region之中(在分代的例子中就是檢查是否老年代中的對(duì)象引用了新生代中的對(duì)象)症见,如果是,便通過CardTable把相關(guān)引用信息記錄到被引用對(duì)象所屬的Region的Remembered Set之中殃饿。當(dāng)進(jìn)行內(nèi)存回收時(shí)谋作,在GC根節(jié)點(diǎn)的枚舉范圍中加入Remembered Set即可保證不對(duì)全堆掃描也不會(huì)有遺漏。

  • 不計(jì)算維護(hù)Remembered Set的操作乎芳,G1收集器的運(yùn)作大致可劃分為以下幾個(gè)步驟:

    初始標(biāo)記(Initial Marking)

    并發(fā)標(biāo)記(Concurrent Marking)

    最終標(biāo)記(Final Marking)

    篩選回收(Live Data Counting and Evacuation)


關(guān)于我

  • 坐標(biāo)杭州遵蚜,普通本科在讀帖池,計(jì)算機(jī)科學(xué)與技術(shù)專業(yè),20年畢業(yè)吭净,目前處于實(shí)習(xí)階段睡汹。
  • 主要做Java開發(fā),會(huì)寫點(diǎn)Golang寂殉、Shell囚巴。對(duì)微服務(wù)、大數(shù)據(jù)比較感興趣不撑,預(yù)備做這個(gè)方向文兢。
  • 目前處于菜鳥階段,各位大佬輕噴焕檬,小弟正在瘋狂學(xué)習(xí)。
  • 歡迎大家和我交流鴨0谋谩J涤蕖!
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末兔辅,一起剝皮案震驚了整個(gè)濱河市腊敲,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌维苔,老刑警劉巖碰辅,帶你破解...
    沈念sama閱讀 206,839評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異介时,居然都是意外死亡没宾,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門沸柔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來循衰,“玉大人,你說我怎么就攤上這事褐澎』岫郏” “怎么了?”我有些...
    開封第一講書人閱讀 153,116評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵工三,是天一觀的道長(zhǎng)迁酸。 經(jīng)常有香客問我,道長(zhǎng)俭正,這世上最難降的妖魔是什么奸鬓? 我笑而不...
    開封第一講書人閱讀 55,371評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮段审,結(jié)果婚禮上全蝶,老公的妹妹穿的比我還像新娘闹蒜。我一直安慰自己,他們只是感情好抑淫,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評(píng)論 5 374
  • 文/花漫 我一把揭開白布绷落。 她就那樣靜靜地躺著,像睡著了一般始苇。 火紅的嫁衣襯著肌膚如雪砌烁。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,111評(píng)論 1 285
  • 那天催式,我揣著相機(jī)與錄音函喉,去河邊找鬼。 笑死荣月,一個(gè)胖子當(dāng)著我的面吹牛管呵,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播哺窄,決...
    沈念sama閱讀 38,416評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼捐下,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了萌业?” 一聲冷哼從身側(cè)響起坷襟,我...
    開封第一講書人閱讀 37,053評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎生年,沒想到半個(gè)月后婴程,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,558評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡抱婉,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評(píng)論 2 325
  • 正文 我和宋清朗相戀三年档叔,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片授段。...
    茶點(diǎn)故事閱讀 38,117評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蹲蒲,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出侵贵,到底是詐尸還是另有隱情届搁,我是刑警寧澤,帶...
    沈念sama閱讀 33,756評(píng)論 4 324
  • 正文 年R本政府宣布窍育,位于F島的核電站卡睦,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏漱抓。R本人自食惡果不足惜表锻,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望乞娄。 院中可真熱鬧瞬逊,春花似錦显歧、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蕾域,卻和暖如春拷肌,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背旨巷。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工巨缘, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人采呐。 一個(gè)月前我還...
    沈念sama閱讀 45,578評(píng)論 2 355
  • 正文 我出身青樓若锁,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親斧吐。 傳聞我的和親對(duì)象是個(gè)殘疾皇子拴清,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評(píng)論 2 345

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