深入理解java虛擬機-jvm垃圾收集器介紹

jvm垃圾收集器介紹

垃圾收集器的描述以及新生代與老年代收集器的搭配

新生代收集器(young generation)

1,serial收集器

是最基本的,發(fā)展最悠久的。是一個單線程收集器,只會使用一個cpu或者一個線程完成垃圾收集。它進行垃圾收集時,必須暫停其他所有的線程直到收集結(jié)束。serial收集器對于運行在client模式下的虛擬機來說是一個很好地選擇。使用標記復(fù)制方法來進行新生代的清理。使用serial收集器:-XX:+UseSerialGC(serial + serial old)

serial收集器

2,ParNew收集器

是serial收集器的多線程版本,除了使用多線程進行垃圾收集之外,其余的行為包括Serial收集器可用的所有控制參數(shù)(例如:-XX:SurvivorRatio、-XX:PretenureSizeThreshold、-XX:HandlePromotionFailure等)、收集算法、stop the world、對象分配規(guī)則、回收策略等都與serial收集器完全一樣,在實現(xiàn)上,兩者公用了相當(dāng)多的代碼。使用ParNew收集器: -XX+UseParNewGC(ParNew + Serial Old)

ParNew收集器

3,Parallel Scavenge收集器

Parallel Scavenge收集器是一個新生代收集器,它也是使用復(fù)制算法的收集器,又是并行的多線程收集器.。parallel Scavenge收集器的目標是達到一個可控制的吞吐量。所謂吞吐量就是CPU用于運行用戶代碼的時間與CPU總消耗時間的比值,吞吐量=運行用戶代碼時間/(運行用戶代碼時間+垃圾收集時間),虛擬機總共運行了100分鐘,其中垃圾收集花掉1分鐘,那吞吐量就是99%。
使用parallel Scavenge收集器: -XX:+UseParallelGC(Parallel Scavenge + Serial Old)-XX:+UseParallelOldGC(Parallel Scavenge + Parallel Old)

Parallel Scavenge收集器提供了兩個參數(shù)用于精確控制吞吐量,分別是控制最大垃圾收集停頓時間-XX:MaxGCPauseMilli參數(shù)以及直接設(shè)置吞吐量大小的-XX:GCTimeRatio參數(shù):

MaxGCPauseMillis參數(shù)允許的值是一個大于0的毫秒數(shù),收集器將盡可能保證內(nèi)存回收花費的時間不超過設(shè)定值。

GCTimeRatio參數(shù)的值應(yīng)當(dāng)是一個大于0且小于100的整數(shù),-XX:GCTimeRatio=nnn:means not more than 1 / (1 + nnn) of the application execution time be spent in the collector。默認為99,就是允許最大1%(即1/(1+99))的垃圾收集時間。

由于與吞吐量關(guān)系密切,Parallel Scavenge收集器也經(jīng)常稱為"吞吐量優(yōu)先"收集器。除上述兩個參數(shù)之外,Parallel Scavenge收集器還有一個參數(shù)-XX:+UseAdaptiveSizePolicy值的關(guān)注。這是一個開關(guān)參數(shù),當(dāng)這個參數(shù)打開之后,就不需要手動指定新生代的大小(-Xmn)、Eden與Survivor區(qū)的比例(-XX:SurvivorRatio)、晉升老年代對象年齡(-XX:PretenureSizeThreshold)等細節(jié)參數(shù)了,虛擬機會根據(jù)當(dāng)前系統(tǒng)的運行情況收集性能監(jiān)控信息,動態(tài)調(diào)整這些參數(shù)以提供最合適的停頓時間或者最大的吞吐量,這種調(diào)節(jié)方式稱為GC自適應(yīng)的調(diào)節(jié)策略(GC Ergonomics)。
使用Parallel Scavenge自適應(yīng)調(diào)節(jié)策略,把內(nèi)存管理的調(diào)優(yōu)交給虛擬機去完成是一個不錯的選擇。只需要把基本的內(nèi)存數(shù)據(jù)設(shè)置好(如 -Xmx設(shè)置最大堆),然后使用MaxGCPauseMillis參數(shù)(更關(guān)注最大停頓時間)或GCTimeRatio(更關(guān)注吞吐量)參數(shù)給虛擬機設(shè)立一個優(yōu)化目標,那具體細節(jié)參數(shù)的調(diào)節(jié)工作就由虛擬機完成了。自適應(yīng)調(diào)節(jié)策略也是Parallel Scavenge收集器與ParNew收集器的一個重要區(qū)別。

Serial,ParNew,Parallel scavenge這幾個新生代收集器都是使用標記復(fù)制方法進行垃圾收集

老年代收集器(old generation)

4,Serial Old收集器

這個收集器的主要意義也是在于給Client模式下的虛擬機使用。如果在Server模式下,那么它主要還有兩大用途:一種用途是在JDK1.5以及之前的版本中與Parallel Scavenge收集器搭配使用,另一種用途就是作為CMS收集器的后備預(yù)案,在并發(fā)收集發(fā)生Concurrent Mode Failure時使用。這兩點都將在后面的內(nèi)容中詳細講解。使用標記清理整理方法來進行垃圾清理。

Serial Old收集器

5,Parallel old收集器

是Parallel Scavenge收集器的老年代版本,使用多線程和"標記-清理-整理"算法。在注重吞吐量以及CPU資源敏感的場合,都可以優(yōu)先考慮Parallel Scavenge加Parallel Old收集器。Parallel Old收集器的工作過程如圖3-9所示。

Parallel Scavenge收集器

6,cms收集器 Concurrent Mark Sweep

是一種以獲取最短回收停頓時間為目標的收集器。目前很大一部分的Java應(yīng)用集中在互聯(lián)網(wǎng)或者B/S系統(tǒng)的服務(wù)端上,這類應(yīng)用尤其重視服務(wù)的響應(yīng)速度,希望系統(tǒng)停頓時間最短,以給用戶帶來較好的體驗。CMS收集器就非常符合這類應(yīng)用的需求。

從名字("Mark Sweep")上看,CMS收集器是基于"標記-清除"算法實現(xiàn)的,它的運作過程相對于前面幾種收集器來說更復(fù)雜一些,整個過程分為4個步驟,包括:
(1)初始標記(CMS initial mark),記錄gc roots直接能引用到的對象,速度很快。
(2)并發(fā)標記(CMS concurrent mark),并發(fā)標記階段就是進行GC Roots Tracing的過程;
(3)重新標記(CMS remark),重新標記階段則是為了修正并發(fā)標記期間因用戶程序繼續(xù)運作而導(dǎo)致標記產(chǎn)生變動的那一部分對象的標記記錄,這個階段的停頓時間一般會比初始標記階段稍長一些,但遠比并發(fā)標記的時間短。
(4)并發(fā)清除(CMS concurrent sweep)

其中,初始標記、重新標記這兩個步驟仍然需要"Stop The World"。初始標記僅僅只是標記一下GC Roots能直接關(guān)聯(lián)到的對象,速度很快;耗時最大的并發(fā)標記和并發(fā)清除過程收集器線程都可以與用戶線程一起工作。總體上來說,CMS收集器的內(nèi)存回收過程是與用戶線程一起并發(fā)執(zhí)行的。


image.png

主要優(yōu)點

  1. 并發(fā)收集、低停頓。

幾個明顯的缺點:

  1. 對CPU資源敏感(會和服務(wù)搶資源);
  2. 無法處理浮動垃圾(在并發(fā)清理階段又產(chǎn)生垃圾,這種浮動垃圾只能等到下一次gc再清理了);
  3. 它使用的回收算法-“標記-清除”算法會導(dǎo)致收集結(jié)束時會有大量空間碎片產(chǎn)生,當(dāng)然通過參數(shù)-XX:+UseCMSCompactAtFullCollection 可以讓jvm在執(zhí)行完標記清除后再做整理
  4. 執(zhí)行過程中的不確定性,會存在上一次垃圾回收還沒執(zhí)行完,然后垃圾回收又被觸發(fā)的情況,特別是在并發(fā)標記和并發(fā)清理階段會出現(xiàn),一邊回收,系統(tǒng)一邊運行,也許沒回收完就再次觸發(fā)full gc,也就是"concurrent mode failure",此時會進入stop the world,用serial old垃圾收集器來回收

parallel Scavenge與cms不能配合工作,老年代使用cms垃圾收集器,那么新生代只能選擇ParNew或者Serial收集器中的一個。

ParNew是使用-XX:+UseConcMarkSweepGC選項后的默認新生代收集器,也可以使用-XX:+UseParNewGC選項來強制指定它。

CMS的相關(guān)參數(shù)

  1. -XX:+UseConcMarkSweepGC:啟用cms
  2. -XX:ConcGCThreads:并發(fā)的GC線程數(shù)
  3. -XX:+UseCMSCompactAtFullCollection:FullGC之后做壓縮整理(減少碎片)
  4. -XX:CMSFullGCsBeforeCompaction:多少次FullGC之后壓縮一次,默認是0,代表每次
    FullGC后都會壓縮一次
  5. -XX:CMSInitiatingOccupancyFraction: 當(dāng)老年代使用達到該比例時會觸發(fā)FullGC(默認
    是92,這是百分比)
  6. -XX:+UseCMSInitiatingOccupancyOnly:只使用設(shè)定的回收閾值(-
    XX:CMSInitiatingOccupancyFraction設(shè)定的值),如果不指定,JVM僅在第一次使用設(shè)定
    值,后續(xù)則會自動調(diào)整
  7. -XX:+CMSScavengeBeforeRemark:在CMS GC前啟動一次minor gc,目的在于減少
    老年代對年輕代的引用,降低CMS GC的標記階段時的開銷,一般CMS的GC耗時 80%都在
    remark階段

7,G1收集器

G1 (Garbage-First)是一款面向服務(wù)器的垃圾收集器,主要針對配備多顆處理器及大容量內(nèi)存的機器. 以極高概率滿足GC停頓時間要求的同時,還具備高吞吐量性能特征.

image.png

G1將Java堆劃分為多個大小相等的獨立區(qū)域(Region),JVM最多可以有2048個Region。一般Region大小等于堆大小除以2048,比如堆大小為4096M,則Region大小為2M,當(dāng)然也可以用參數(shù)"-XX:G1HeapRegionSize"手動指定Region大小,但是推薦默認的計算方式。G1保留了年輕代和老年代的概念,但不再是物理隔閡了,它們都是(可以不連續(xù))Region的集合。
默認年輕代對堆內(nèi)存的占比是5%,如果堆大小為4096M,那么年輕代占據(jù)200MB左右的內(nèi)存,對應(yīng)大概是100個Region,可以通過“-XX:G1NewSizePercent”設(shè)置新生代初始占比,在系統(tǒng)運行中,JVM會不停的給年輕代增加更多的Region,但是最多新生代的占比不會超過60%,可以通過“-XX:G1MaxNewSizePercent”調(diào)整。年輕代中的Eden和Survivor對應(yīng)的region也跟之前一樣,默認8:1:1,假設(shè)年輕代現(xiàn)在有1000個region,eden區(qū)對應(yīng)800個,s0對應(yīng)100個,s1對應(yīng)100個。
一個Region可能之前是年輕代,如果Region進行了垃圾回收,之后可能又會變成老年代,也就是說Region的區(qū)域功能可能會動態(tài)變化。
G1垃圾收集器對于對象什么時候會轉(zhuǎn)移到老年代跟之前講過的原則一樣,唯一不同的是對大對象的處理,G1有專門分配大對象的Region叫Humongous區(qū),而不是讓大對象直接進入老年代的Region中。在G1中,大對象的判定規(guī)則就是一個大對象超過了一個Region大小的50%,比如按照上面算的,每個Region是2M,只要一個大對象超過了1M,就會被放入Humongous中,而且一個大對象如果太大,可能會橫跨多個Region來存放。
Humongous區(qū)專門存放短期巨型對象,不用直接進老年代,可以節(jié)約老年代的空間,避免因為老年代空間不夠的GC開銷。
Full GC的時候除了收集年輕代和老年代之外,也會將Humongous區(qū)一并回收。

G1收集器一次GC的運作過程大致分為以下幾個步驟:

  • 初始標記(initial mark,STW):暫停所有的其他線程,并記錄下gc roots直接能引用的對象,速度很快 ;
  • 并發(fā)標記(Concurrent Marking):同CMS的并發(fā)標記
  • 最終標記(Remark,STW):同CMS的重新標記
  • 篩選回收(Cleanup,STW):篩選回收階段首先對各個Region的回收價值和成本進行排序,根據(jù)用戶所期望的GC停頓時間(可以用JVM參數(shù) -XX:MaxGCPauseMillis指定)來制定回收計劃,比如說老年代此時有1000個Region都滿了,但是因為根據(jù)預(yù)期停頓時間,本次垃圾回收可能只能停頓200毫秒,那么通過之前回收成本計算得知,可能回收其中800個Region剛好需要200ms,那么就只會回收800個Region,盡量把GC導(dǎo)致的停頓時間控制在我們指定的范圍內(nèi)。這個階段其實也可以做到與用戶程序一起并發(fā)執(zhí)行,但是因為只回收一部分Region,時間是用戶可控制的,而且停頓用戶線程將大幅提高收集效率。不管是年輕代或是老年代,回收算法主要用的是復(fù)制算法,將一個region中的存活對象復(fù)制到另一個region中,這種不會像CMS那樣回收完因為有很多內(nèi)存碎片還需要整理一次,G1采用復(fù)制算法回收幾乎不會有太多內(nèi)存碎片。


    image.png

G1收集器在后臺維護了一個優(yōu)先列表,每次根據(jù)允許的收集時間,優(yōu)先選擇回收價值最大的Region(這也就是它的名字Garbage-First的由來),比如一個Region花200ms能回收10M垃圾,另外一個Region花50ms能回收20M垃圾,在回收時間有限情況下,G1當(dāng)然會優(yōu)先選擇后面這個Region回收。這種使用Region劃分內(nèi)存空間以及有優(yōu)先級的區(qū)域回收方式,保證了G1收集器在有限時間內(nèi)可以盡可能高的收集效率。

具備以下特點:

  1. 并行與并發(fā):G1能充分利用多CPU、多核環(huán)境下的硬件優(yōu)勢,使用多個CPU(CPU或者CPU核心)來縮短Stop-The-World停頓的時間,G1收集器仍然可以通過并發(fā)的方式讓java程序繼續(xù)執(zhí)行。
  2. 分代收集:雖然G1可以不需要其他收集器配合就能獨立管理整個GC堆,但它能夠采用不同的方式去處理新創(chuàng)建的對象和已經(jīng)存活了一段時間、熬過多次GC的舊對象以獲取更好的收集效果。
  3. 空間整合:與CMS的"標記-清理"算法不同,G1從整體上來看是基于"標記-整理"算法實現(xiàn)的收集器,從局部上看是基于"復(fù)制"算法實現(xiàn)的,但無論如何,這幾個算法都意味著G1運行期間不會產(chǎn)生內(nèi)存碎片,收集后能提供規(guī)整的可用內(nèi)存。
  4. 可預(yù)測的停頓:這是G1相對于CMS的另一大優(yōu)勢,降低停頓時間是G1和CMS共同的關(guān)注點。G1除了追求低停頓外,還能建立可預(yù)測的停頓啥時間模型,可以明確指定在一個長度為M毫秒的時間片段內(nèi),消耗在垃圾收集上的時間不得超過N毫秒,這幾乎已經(jīng)是實時Java(RTSJ)的垃圾收集器的特征了。

G1垃圾收集分類

YoungGC
YoungGC并不是說現(xiàn)有的Eden區(qū)放滿了就會馬上觸發(fā),而且G1會計算下現(xiàn)在Eden區(qū)回收大概要多久時間,如果回收時間遠遠小于參數(shù) -XX:MaxGCPauseMills 設(shè)定的值,那么增加年輕代的region,繼續(xù)給新對象存放,不會馬上做Young GC,直到下一次Eden區(qū)放滿,G1計算回收時間接近參數(shù) -XX:MaxGCPauseMills 設(shè)定的值,那么就會觸發(fā)Young GC

MixedGC
不是FullGC,老年代的堆占有率達到參數(shù)(-XX:InitiatingHeapOccupancyPercen)設(shè)定的值則觸發(fā),回收所有的Young和部分Old(根據(jù)期望的GC停頓時間確定old區(qū)垃圾收集的優(yōu)先順序)以及大對象區(qū),正常情況G1的垃圾收集是先做MixedGC,主要使用復(fù)制算法,需要把各個region中存活的對象拷貝到別的region里去,拷貝過程中如果發(fā)現(xiàn)沒有足夠的空region能夠承載拷貝對象就會觸發(fā)一次Full GC

Full GC
停止系統(tǒng)程序,然后采用單線程進行標記、清理和壓縮整理,好空閑出來一批Region來供下一次MixedGC使用,這個過程是非常耗時的。

G1垃圾收集器優(yōu)化建議

假設(shè)參數(shù) -XX:MaxGCPauseMills 設(shè)置的值很大,導(dǎo)致系統(tǒng)運行很久,年輕代可能都占用了堆內(nèi)存的60%了,此時才觸發(fā)年輕代gc。那么存活下來的對象可能就會很多,此時就會導(dǎo)致Survivor區(qū)域放不下那么多的對象,就會進入老年代中。

或者是你年輕代gc過后,存活下來的對象過多,導(dǎo)致進入Survivor區(qū)域后觸發(fā)了動態(tài)年齡判定規(guī)則,達到了Survivor區(qū)域的50%,也會快速導(dǎo)致一些對象進入老年代中。
所以這里核心還是在于調(diào)節(jié) -XX:MaxGCPauseMills 這個參數(shù)的值,在保證他的年輕代gc別太頻繁的同時,還得考慮每次gc過后的存活對象有多少,避免存活對象太多快速進入老年代,頻繁觸發(fā)mixed gc.

2 理解GC日志

33.125: [GC [DefNew: 3324K->152K(3712K), 0.0025925 secs] 3324K->152K(11904K), 0.0031680 secs]
100.667: [Full GC [Tenured: 0K->210K(10240K), 0.0149142 secs] 4603K->210K(19456K), [Perm : 2999K->2999K(21248K)], 0.0150007 secs] [Times: user=0.01 sys=0.00, real=0.02 secs]

最前面的數(shù)字"33.125"和"100.667" 代表了GC發(fā)生的時間,這個數(shù)字的含義是從Java虛擬機啟動以來經(jīng)歷的秒數(shù)。

"[GC"和"[Full gc"說明了這次垃圾收集的停頓類型,書中說:而不是用來區(qū)分新生代GC還會老年代GC的。如果有"full",說明這次GC是發(fā)生了Stop-The-World的。我理解新生代和老年代GC都會發(fā)生Stop-The-World,只是老年代的STW的時間相對更長 GC說明垃圾回收發(fā)生在新生代,F(xiàn)ull GC說明垃圾回收發(fā)生在新生代和老年代

[DefNew、[Tenured、[Perm 表示GC發(fā)生的區(qū)域,這里顯示的區(qū)域名稱與使用的GC收集器是密切相關(guān)的。serial收集器的新生代名稱為"Default New Generation",所以顯示"[DefNew" 。如果是ParNew收集器,新生代名稱就會變成"[ParNew"意為"Parallel New Generation"。如果采用Parallel Scavenge收集器,那么它配套的新生代稱為"PSYoungGen",老年代和永久代同理,名稱也是由收集器決定的。

后面的方括號內(nèi)部的"3324K-> 152K(3712K)" 含義是"GC前該內(nèi)存區(qū)域已使用容量-> GC后該內(nèi)存區(qū)域已使用容量(該內(nèi)存區(qū)域總?cè)萘浚?, 3324K->152K(11904K)含義是"GC前整個堆的占用量-> GC后整個堆的占用量(堆的總大小)"

再往后,"0.0025925secs"表示該內(nèi)存區(qū)域GC所占用的時間,單位是秒。

參考
gc日志解析:https://plumbr.io/handbook/garbage-collection-algorithms-implementations

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

對象優(yōu)先在eden分配

public class TestAllocation {

    private static final int _1MB = 1024 * 1024;
    public static void main(String[] args) {
        byte[] allocation1, allocation2, allocation3, allocation4;
        allocation1 = new byte[2 * _1MB];
        allocation2 = new byte[2 * _1MB];
        allocation3 = new byte[2 * _1MB];
        allocation4 = new byte[4 * _1MB]; // 出現(xiàn)一次Minor GC
    }
}

運行結(jié)果:


image.png

這次GC發(fā)生的原因是給allocation4分配內(nèi)存時,發(fā)現(xiàn)Eden已經(jīng)被占用了6MB,剩余空間已不足以分配案例location4所需的4MB的內(nèi)存,因此發(fā)生minor FC。GC期間虛擬機又發(fā)現(xiàn)已有3個2MB大小的對象全部無法放入到Survivor空間(Survivor只有1MB大小),所以只好通過分配擔(dān)保機制提前轉(zhuǎn)移到老年代去。

新生代GC(Minor GC): 指發(fā)生在新生代的垃圾收集動作,因為java對象大多都具備朝生夕死的特性,所以Minor GC非常頻繁,一般回收速度也比較快。

老年代GC(Major GC /Full GC):指發(fā)生在老年代的GC,出現(xiàn)了Major GC,經(jīng)常會伴隨至少一次的Minor GC,Major GC的速度一般比Minor GC慢10倍以上。

大對象直接進入老年代

-XX:PretenureSizeThreshold參數(shù),令大于這個設(shè)置值的對象直接在老年代分配。這樣做目的是避免在Eden區(qū)以及兩個Survivor區(qū)之間發(fā)生大量的內(nèi)存復(fù)制(新生代使用復(fù)制算法收集內(nèi)存)

public class TestAllocation1 {

    private static final int _1MB = 1024 * 1024;
    public static void main(String[] args) {
        byte[] allocation;
        allocation = new byte[4* _1MB];     
    }
}

運行結(jié)果:


image.png

老年代的10MB空間被使用了40%,也就是4MB的allocation對象直接分配在老年代中,這是因為PretenureSizeThreshold被設(shè)置為3MB,因此超過3MB的對象都會直接在老年代進行分配。(PretenureSizeThreshold參數(shù)只對Serial和ParNew兩款收集器有效,Parallel Scavenge收集器不認識這個參數(shù))

長期存活對象進入老年代


public class TestTenuringThreshold {

    private static final int _1MB = 1024 * 1024;
    public static void main(String[] args) {
        byte[] allocation1, allocation2, allocation3;
        allocation1 = new byte[ _1MB/16];
        allocation2 = new byte[4 * _1MB];
        allocation3 = new byte[4 * _1MB]; // 第一次Minor GC
        allocation3 = null;
        allocation3 = new byte[4 * _1MB]; // 第二次Minor GC
    }
}
~                  

當(dāng)MaxTenuringThreshold=1時,allocation3=new byte[4*_1MB] 第一次賦值時,因為eden區(qū)總空間為8192K,剩余空間不足4096K,所以會觸發(fā)一次minor GC。觸發(fā)GC后allocation1進入from區(qū)域,年齡為1,allocation2空間的大于suvivor的空間1MB,所以直接分配到老年代,allocation3分配到eden區(qū)占用51%的eden區(qū)空間。
allocation3=new byte[4*_1MB]第二次賦值時,eden區(qū)總空間為8192K,空間被占用51% eden區(qū)空間不足,所以觸發(fā)第二次Minor GC。第二次的Minor GC觸發(fā)后,由于MaxTenuringThreshold=1所以age=1的allocation1被提升到老年代,surivior的from區(qū)空間被清空,allocation3對象由于沒有被GC root引用,所有allocation3原來的空間被回收,再次被分配給新的申明的allocation3對象。

MaxTenuringThreshold=15時,流程大部分與上面相同,不同的地方在于age=1的allocation1經(jīng)過第二次GC后還是停留在surivior的from區(qū),不進入tenured generation老年代。

-XX:MaxTenuringThreshold=1
-XX:MaxTenuringThreshold=15

動態(tài)對象年齡的判定

public class TestTenuringThreshold2 {

    private static final int _1MB = 1024 * 1024;
    public static void main(String[] args) {
        byte[] allocation1, allocation2, allocation3,allocation4;
        allocation1 = new byte[ _1MB/4];
        allocation4 = new byte[ _1MB/4];
        allocation2 = new byte[4 * _1MB];
        allocation3 = new byte[4 * _1MB];// 出現(xiàn)一次Minor GC
        allocation3 = null;
        allocation3 = new byte[4 * _1MB]; // 出現(xiàn)一次Minor GC
    }
}

如果在Surivor空間的相同年齡所有對象大小總和大于Survivor空間的一半,年齡大于或等于該年齡的對象就可以直接進入老年代,無需等到MaxTenuringThreshold中要求的年齡。
上面allocation1與allocation4的對象加起來超過512KB并且是同年的,滿足同年對象達到Survivor空間的一半規(guī)則。

image.png

空間擔(dān)保

JDK 6 Update 24之后的規(guī)則變?yōu)橹灰夏甏倪B續(xù)空間大于新生代對象總大小或者歷次晉升的平均大小就會進行Minor GC,否則進行Full GC。如果HandlePromotionFailure失敗,那就只好在失敗后重新發(fā)起一次Full GC。

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,327評論 6 537
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,996評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,316評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,406評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 72,128評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,524評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,576評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,759評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,310評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,065評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,249評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,821評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,479評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,909評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,140評論 1 290
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,984評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 48,228評論 2 375