貴州安順建設(shè)主管部門網(wǎng)站百度seo網(wǎng)站優(yōu)化
? ? ? ? jvm的垃圾回收算法有標記-清除、復(fù)制、標記-整理、分代回收算法,它們分別有不同的實現(xiàn):
一、標記-清除算法
? ? ? ? 利用可達性分析算法分析之后,將未被標記的對象[即不可達對象]清除,以便回收它們所占用的內(nèi)存。
缺點:
? ? ? ? 1、需要對內(nèi)存進行兩次遍歷,一次遍歷標記,一次遍歷清除,效率較低;
? ? ? ? 2、這種算法會造成大量的內(nèi)存碎片,以至于出現(xiàn)當(dāng)我們需要一片連續(xù)的大的內(nèi)存空間去存儲對象的時候無法找到合適的內(nèi)存。
? ? ? ? CMS收集器就是用的標記-清除算法,CMS為了解決碎片式內(nèi)存提供了內(nèi)存合并整理的功能,但是這個功能的執(zhí)行會導(dǎo)致用戶線程暫停,會延長STW,導(dǎo)致程序性能下降。
二、復(fù)制算法:
? ? ? ? 為了解決清除算法的內(nèi)存碎片問題,復(fù)制算法將內(nèi)存一分為二,每次只使用一半的內(nèi)存去存儲對象,當(dāng)這一半內(nèi)存不夠用的時候觸發(fā)gc,將存活下來的對象移到另外一半內(nèi)存,然后將當(dāng)前這一半內(nèi)存清空,以便在下一次gc的時候使用。
? ? ? ? 復(fù)制算法是沒有標記過程的,它在可達性分析的過程中將存活的對象直接復(fù)制到另一半內(nèi)存。而標記過程是為了找出未被標記的對象來進行清除。
缺點
????????每次只能使用一半內(nèi)存,內(nèi)存使用率低,gc頻繁。
改進
? ? ? ? 在新生代中,因為大部分的對象都是朝生夕死,每次gc存活下來的對象占比很少,所以將新生代按照8:1:1的比例劃分為Eden、survivor from、survivor to三個區(qū),每次minor gc時,都是將eden和一個survivor區(qū)存活下來的對象復(fù)制到另外一個survivor區(qū),然后清空eden和對應(yīng)的survivor區(qū)。雖然我們其實是無法保證每次minor gc過后存活下來的對象占比永遠低于10%,但是有老年代為新生代做內(nèi)存兜底,當(dāng)存活下來的對象在另一個survivor區(qū)保存不下時,將這些對象轉(zhuǎn)移到老年代。
三、標記-整理算法?
?????????先對對象進行標記,然后將存活下來的對象向內(nèi)存的一端移動,然后回收不再存活的對象所占用的內(nèi)存。標記整理算法是針對于老年代提出來的算法,因為老年代的大部分對象都是經(jīng)過了很多次gc之后仍然存活的對象,這些對象生存率高,如果對它們使用復(fù)制算法的話,就會造成一次次的復(fù)制而浪費時間。
四、分代收集算法?
? ? ? ? 因為新生代和老年代的對象有著不同的特點,新生代存放的是大部分的新創(chuàng)建的對象,這些對象大部分都是朝生夕死,因此每次minor gc都會有大量的對象被回收;而老年代的對象是經(jīng)歷了多次gc依然存活下來的對象,老年代中的對象存活率高。所以我們不適合將新生代和老年代的對象一起gc,新生代和老年代適合不同的gc算法,并且適合在不同的時機去觸發(fā)gc。新生代使用復(fù)制算法,老年代使用標記整理或清除算法?,F(xiàn)在的商用的虛擬機都是使用分代收集。?
?
CMS和G1?
? ? ? ? cms收集器只回收老年代,使用標記-清除算法;G1既回收新生代又回收老年代,使用標記-整理算法。
? ? ? ? CMS因為其使用的是標記-清除算法,所以會有個嚴重問題就是在gc之后產(chǎn)生大量的內(nèi)存碎片,當(dāng)我們無法找到一塊兒足夠大的連續(xù)內(nèi)存去存儲對象的時候,就不得不再一次觸發(fā)gc。
? ? ? ? G1打破了原有的對于堆的分代概念,將堆分為一個個大小相等的region,并且提供了可預(yù)測的停頓時間模型,使得我們可以去設(shè)置在一定的時長內(nèi)所期望的停頓時間,在執(zhí)行g(shù)c的時候,會將region按照回收價值和回收耗時進行排序,依據(jù)我們所設(shè)置的期望停頓時間去制定一個回收方案,回收部分region。
? ? ? ? G1的優(yōu)勢很明顯,它無需和其他的收集器配合,自己便可以回收新生代和老年代;它支持可預(yù)期的停頓時間,提高了gc的效率。
垃圾回收的觸發(fā)時機?
新生代垃圾回收觸發(fā)時機:
????????當(dāng) eden 區(qū)內(nèi)存無法為一個新對象分配內(nèi)存時,就會觸發(fā) Minor GC
老年代垃圾回收觸發(fā)時機:
????????1、如果沒有設(shè)置-XX:+UseCMSInitiatingOccupancyOnly,虛擬機會根據(jù)收集的數(shù)據(jù)決定是否觸發(fā)(建議線上環(huán)境帶上這個參數(shù),不然會加大問題排查的難度)。
????????2、老年代使用率達到閾值?CMSInitiatingOccupancyFraction
,默認92%。
????????3、永久代的使用率達到閾值?CMSInitiatingPermOccupancyFraction
,默認92%,前提是開啟?CMSClassUnloadingEnabled
。
????????4、新生代的晉升擔(dān)保失敗。老年代沒有足夠的空間來容納全部的新生代對象或歷史平均晉升到老年代的對象,如果不夠的話,就提早進行一次老年代的回收,防止下次進行YGC的時候發(fā)生晉升失敗。
老年代空間分配擔(dān)保規(guī)則
????????在執(zhí)行任何一次Minor GC之前,JVM會先檢查一下老年代的可用內(nèi)存空間,是否大于新生代所有對象的總大小。因為在極端的情況下,可能新生代Minor GC過后,所有對象都存活下來了,并且所有對象全部要晉升到老年代,老年代得有足夠的空間去存儲它們。
????????假如Minor GC之前,發(fā)現(xiàn)老年代的可用內(nèi)存已經(jīng)小于了新生代的全部對象大小了,就會看一下“-XX:-HandlePromotionFailure”的參數(shù)是否設(shè)置了如果有這個參數(shù),那么就會繼續(xù)嘗試進行下一步判斷。
????????下一步判斷,就是看看老年代的內(nèi)存大小,是否大于之前每一次Minor GC后進入老年代的對象的平均大小。
????????舉個例子,之前每次Minor GC后,平均都有10MB左右的對象會進入老年代,那么此時老年代可用內(nèi)存大于10MB。
????????這就說明,很可能這次Minor GC過后也是差不多10MB左右的對象會進入老年代,此時老年代空間是夠的,
????????如果上面那個步驟判斷失敗了,或者是“-XX:-HandlePromotionFailure”參數(shù)沒設(shè)置,此時就會直接觸發(fā)一次“Full GC”,就是對老年代進行垃圾回收,盡量騰出來一些內(nèi)存空間,然后再執(zhí)行Minor GC。
????????如果上面兩個步驟都判斷成功了,那么就是說可以冒點風(fēng)險嘗試一下Minor GC。此時進行Minor GC有幾種可能。
????????第一種可能,Minor GC過后,剩余的存活對象的大小,是小于Survivor區(qū)的大小的,那么此時存活對象進入Survivor區(qū)域即可。
????????第二種可能,Minor GC過后,剩余的存活對象的大小,是大于 Survivor區(qū)域的大小,但是是小于老年代可用內(nèi)存大小的,此時就直接進入老年代即可。
????????第三種可能,很不幸,Minor GC過后,剩余的存活對象的大小,大于了Survivor區(qū)域的大小,也大于了老年代可用內(nèi)存的大小。此時老年代都放不下這些存活對象了,就會發(fā)生“Handle Promotion Failure”的情況,這個時候就會觸發(fā)一次“Full GC”。
????????Full GC就是對老年代進行垃圾回收,同時也一般會對新生代進行垃圾回收。因為這個時候必須得把老年代里的沒人引用的對象給回收掉,然后才可能讓Minor GC過后剩余的存活對象進入老年代里面。如果要是Full GC過后,老年代還是沒有足夠的空間存放Minor GC過后的剩余存活對象,那么此時就會導(dǎo)致所謂的“OOM”內(nèi)存溢出了。因為內(nèi)存實在是不夠了,你還是要不停的往里面放對象,當(dāng)然就崩潰了。
?
????????