Java虚拟机JVM常用的几种回收算法和垃圾回收器
1. 垃圾回收算法
1.1 “標(biāo)記-清除”算法
對內(nèi)存對象進行可達性分析并標(biāo)記,標(biāo)記完成后統(tǒng)一回收。書中說有兩個不足:①標(biāo)記和清除效率不高;②內(nèi)存空間是大量不連續(xù)的內(nèi)存碎片。標(biāo)記是每個回收算法都要經(jīng)歷的,而且在標(biāo)記后,清除也是每個算法都要經(jīng)歷的,只是方式不同,所以我覺得標(biāo)記和清除效率不高不是“標(biāo)記-清除”算法的不足,而是每個算法都有,最主要的問題還是內(nèi)存空間是大量不連續(xù)內(nèi)存碎片。
1.2 “復(fù)制”算法
將內(nèi)存空間分為兩塊,每次只使用其中一塊內(nèi)存空間。當(dāng)內(nèi)存空間滿了,將還存活的對象復(fù)制到另一塊內(nèi)存空間,再將當(dāng)前內(nèi)存空間直接清空即可。由于新生代對象生存周期短,所以沒必要1:1分配空間,常用的方式是將內(nèi)存空間分為一塊Eden和兩塊Survivor區(qū)域,之間比例是8:1:1,每次要垃圾回收時,將Eden和其中一個Survivor還存活的內(nèi)存對象復(fù)制到另一塊Survivor內(nèi)存即可,然后將原先的Eden和Survivor清空即可。如果Survivor存不下要復(fù)制的內(nèi)存對象,那么需要將多余的對象放入老年代,如果多余的對象小于老年代內(nèi)存空間,那么此次的Minor GC垃圾回收方案是成功的;但如果多余的對象大于老年代內(nèi)存空間,則要判斷HandlePromotionFailure標(biāo)志位是否允許分配擔(dān)保,如果不允許,那么直接進行Full GC;如果允許,那么判斷老年代剩余的內(nèi)存空間是否大于歷次進入老年代的內(nèi)存對象,如果大于,那么會進行一次有風(fēng)險的Minor GC,如果Minor GC失敗了再進行Full GC。為了避免Full GC,一般允許分配擔(dān)保。最主要的問題是對于生存周期長的對象來說,會復(fù)制多次,此時效率變低。
1.3 “標(biāo)記-整理”算法
先標(biāo)記所有存活的對象,然后讓對象往內(nèi)存空間一端移動,直接清除邊界外的內(nèi)存空間。
1.4 “分代”回收算法
年輕代對象生存周期短,那么使用復(fù)制算法;而老年代對象生存周期長,使用“標(biāo)記-清除”或“標(biāo)記-整理”算法。
2. 垃圾回收器
垃圾回收分為新生代和老年代回收,不同代有不同的回收器,先放一張《深入理解java虛擬機》書中回收器的搭配圖,如下。
2.1 Serial回收器
新生代回收器,使用“復(fù)制”回收算法。單線程處理垃圾回收,并在處理垃圾時,暫停所有用戶線程。優(yōu)點是簡單高效,對于內(nèi)存空間幾百兆來說,垃圾回收導(dǎo)致用戶線程暫停時間可以控制在幾十毫秒內(nèi),對用戶的影響可接受。對應(yīng)的老年代回收器是Serial Old,“標(biāo)記-整理”回收算法。
? ? ? ?
在垃圾回收中,并行指有多條垃圾回收線程回收垃圾;而并發(fā)指垃圾回收線程和用戶線程一起運行。
2.2 ParNew回收器
多線程版的Serial回收器(并行回收器),也是使用“復(fù)制”回收方式。還有一個特點就是它可以和CMS老年代回收器一起搭配使用。
2.3 Parallel Scavenge回收器
也是一個多線程版的“復(fù)制”算法回收器(并行回收器),唯一不同的是其它垃圾回收器是盡量縮短用戶線程暫停的時間,而它的關(guān)注點是吞吐量,吞吐量=用戶代碼運行時間/(用戶代碼運行時間+垃圾收集時間)。提高吞吐量可以高效利用CPU。可通過控制最大垃圾回收停頓時間-XX:MaxGCPauseMills和吞吐量大小-XX:GCTimeRatio兩個參數(shù)控制吞吐量。對應(yīng)的老年代回收器是Parallel Old,“標(biāo)記-整理”回收算法。
2.4 Concurrent Mark Sweep(CMS)回收器
多線程的老年代回收器(并行、并發(fā)回收器),采用“標(biāo)記-清除”算法,以最短回收停頓時間為目標(biāo)。主要有初始標(biāo)記、并發(fā)標(biāo)記、重新標(biāo)記以及并發(fā)清除四個步驟。初始標(biāo)記:標(biāo)記GC Roots能直接關(guān)聯(lián)的需;并發(fā)標(biāo)記:進行GC Roots跟蹤各個節(jié)點的過程;重新標(biāo)記(并行階段):修正并發(fā)標(biāo)記期間用戶程序更改的那些標(biāo)記對象;由于最耗時的并發(fā)標(biāo)記和并發(fā)清除可以與用戶線程一起工作,所以整體回收使用戶線程暫停的時間很短。缺點:①并發(fā)階段會占用一部分CPU資源,導(dǎo)致吞吐量降低;②使用“標(biāo)記-清除”算法,會有大量的內(nèi)存碎片存在。③無法處理浮動垃圾,并發(fā)清除過程,用戶線程產(chǎn)生的垃圾只能下次清理。
2.5 Garbage-First(G1)回收器
新生代(復(fù)制算法)、老年代(標(biāo)記-整理)一體的回收器。使用G1回收器,堆內(nèi)存被劃分為多個大小(1~32MB)相等的區(qū)域(默認(rèn)是2048個)。回收步驟:①初始標(biāo)記;②并發(fā)標(biāo)記;③最終標(biāo)記;④篩選回收。前三個步驟與CMS一樣,根據(jù)用戶期望的GC停頓時間優(yōu)先回收價值最大(回收所獲得的空間大小以及回收所需時間)的內(nèi)存區(qū)域。優(yōu)點就是可以根據(jù)用戶設(shè)定的GC停頓時間來制定區(qū)域的垃圾回收列表。
3. 內(nèi)存分配
3.1 對象優(yōu)先在新生代的Eden中分配內(nèi)存
3.2 大對象(長字符串或長數(shù)組)直接進入老年代
3.3 長期存活的對象將進入老年代:對象在Eden創(chuàng)建,經(jīng)過Minor GC并能被Survivor容納,將被移動到Survivor空間中,并且對象年齡設(shè)為1;然后再Survivor中每經(jīng)歷一次Minor GC,年齡就增加一歲,默認(rèn)增加到15歲晉升到老年代,可通過-xx:MaxTenuringThreshold設(shè)置。
3.4 年齡動態(tài)判定:如果Survivor空間中相同年齡對象總和大小超過Survivor空間的一半,那么年齡大于或等于該年齡的對象可進入老年代。
與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的Java虚拟机JVM常用的几种回收算法和垃圾回收器的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 浅谈Java虚拟机JVM的垃圾回收机制
- 下一篇: 分析对象内部结构,并详解synchron