Minor GC,Major GC,Full GC -- hotspot VM GC讲解
生活随笔
收集整理的這篇文章主要介紹了
Minor GC,Major GC,Full GC -- hotspot VM GC讲解
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
針對HotSpot VM的實現(xiàn),它里面的GC其實準(zhǔn)確分類只有兩大種:
--串行(–XX:+UseSerialGC )Out of Box算法,年輕代串行復(fù)制,年老代串行標(biāo)記整理,主要用于桌面應(yīng)用
--并行(–XX:+UseParallelGC )年輕代暫停應(yīng)用程序,多個垃圾收集線程并行的復(fù)制收集,年老代暫停應(yīng)用程序,與串行收集器一樣,單垃圾收集線程標(biāo)記整理。JDK 6.0啟用該算法后,默認(rèn)啟用了-XX:+UseParallelOldGC,性能大為提高
--并發(fā)(Concurrent Low Pause Collector)( –XX:+UseConcMarkSweepGC )啟用該參數(shù),默認(rèn)啟用了-XX:+UseParNewGC;簡單的說,并發(fā)是指用戶線程與垃圾收集線程并發(fā),程序在繼續(xù)運行,而垃圾收集程序運行于其他CPU上。
---目前客戶端應(yīng)用程序采用上述兩種收集器。服務(wù)器端一般采用CMS 和 G1垃圾收集器,Java9 將默認(rèn)采用G1垃圾收集器。
這張圖來自于《深入理解Java虛擬機--jvm最高特性與最佳實踐 ? ?周志明》,這張圖也是很多Java初學(xué)者了解Hotspot GC需要記住了解的圖。下面 就說明一下圖中這些minor GC,先說serialNew 和 serialOld 這個是單線程的,也就是stop all of world,當(dāng)然其他的GC,比如parallelOld 和 parNew雖是多線程收集,但是還是stop the world.serialold 或者 serialNew 單線程,回收效率較低,那么為什么現(xiàn)在還在使用???那是因為其算法簡單,停止所有應(yīng)用線程去專心收集垃圾,收集效率極高,幾乎把你所有沒有使用到的對象垃圾都給你收回來。專心做收集,那么你的內(nèi)存空間能多大呢?還不得幾十毫秒或者幾百毫秒就給你搞定的事情。停頓也是極短的時間。所以這個垃圾回收器一直都在使用。在client程序中也是主導(dǎo)的。
parNew 和 parallel Old 垃圾回收器和serial很相近,無非就是使用了多線程,目的就是借助處理器的多核能力。(畢竟現(xiàn)在處理器都是多核的)
parallel Scavenge 這個較為特殊的GC,其目的是為了實現(xiàn)最大的吞吐量,吞吐量=用戶任務(wù)處理時間 / (用戶處理時間 + 垃圾回收時間);說白了我就是給用戶開口讓其設(shè)置參數(shù)來限制垃圾回收的時間,怎么限制垃圾回收時間,就是讓垃圾不是那么徹底的回收干凈,犧牲一定的yong 代空間,那么我讓你回收時間縮短,增加吞吐量。
CMS consurrent mark sweep 這個回收器是在old 代的,主要和其他yong代配合使用,上述圖中,只要垃圾回收器之間有連接線,那么就可以配合使用。CMS看其名稱就知道基于標(biāo)記-清除算法,標(biāo)記清除-清除算法,有好處,啥好處?就是省空間,不復(fù)制,不節(jié)省空間嘛。但是產(chǎn)生垃圾碎片,導(dǎo)致存儲空間不連續(xù)。有沒有好的垃圾清除算法(垃圾清除算法主要就是標(biāo)記算法,復(fù)制算法,標(biāo)記-清除算法,標(biāo)記整理算法),好的算法就是標(biāo)記-整理算法,但是復(fù)雜呀!!!CMS是要降低停頓時間,你搞個那么復(fù)雜的算法,回收時間咋控制。 CMS工作主要分為四個步驟,初始標(biāo)記--并發(fā)標(biāo)記--重復(fù)標(biāo)記--并發(fā)清除;初始標(biāo)記和重復(fù)標(biāo)記是stop the word,為啥??? 標(biāo)記的時候為了標(biāo)記的準(zhǔn)確同時對整個old空間都做標(biāo)記,應(yīng)用線程不得停頓嘛!并發(fā)標(biāo)記的時候是基于初始標(biāo)記的結(jié)果,所以用戶線程可以運行,所以這個過程是并發(fā)的。重復(fù)標(biāo)記是同一個道理,回收的時候,就是多線程并發(fā)回收。CMS在回收的時候由于分多個過程,回收時間也稍稍長,那么這個過程中,用戶線程并發(fā)性能回收影響。
在CMS收集垃圾的時候,會給用戶線程留點空間,用于用戶存儲old數(shù)據(jù),如果在垃圾回收的過程中,這塊小區(qū)域滿了,那么用戶線程都要被停止。
G1垃圾回收器,garbage first,就是講堆區(qū)劃分很多的區(qū)域塊,優(yōu)先回收優(yōu)先級較高的區(qū)域,而且會綜合之前回收的經(jīng)驗,統(tǒng)計便于收集或者這塊區(qū)域較為重要,或者垃圾較多的區(qū)域,對其優(yōu)先收集。而且在手機過程中,其他區(qū)域是可以提供給用戶開銷的,所以G1幾乎使得用戶線程不停頓。 三、Java內(nèi)存的調(diào)優(yōu)參數(shù)-Xmx1024m:設(shè)置JVM最大可用內(nèi)存為1024M。
-Xms1024m:設(shè)置JVM促使內(nèi)存為1024M。此值可以設(shè)置與-Xmx相同,以避免每次垃圾回收完成后JVM重新分配內(nèi)存。
-Xmn512m:設(shè)置年輕代大小為512M。(持久代一般固定大小為64m,所以增大年輕代后,將會減小年老代大小。此值對系統(tǒng)性能影響較大,Sun官方推薦配置為整個堆的3/8。)
-Xss128k:設(shè)置每個線程的堆棧大小。這個值可以根據(jù)應(yīng)用的線程所需內(nèi)存大小進(jìn)行調(diào)整。在相同物理內(nèi)存下,減小這個值能生成更多的線程。但是操作系統(tǒng)對一個進(jìn)程內(nèi)的線程數(shù)還是有限制的,不能無限生成。
-XX:NewRatio=4設(shè)置年輕代(包括Eden和兩個Survivor區(qū))與年老代的比值(總的大小是Xms的值)。設(shè)置為4,則年輕代與年老代所占比值為1:4,年輕代占整個堆棧的1/5。舉個例子,-Xms 設(shè)置為 1024m,-Xmx 也設(shè)置為 1024m的情況下:·年輕代 = 1024M/5 = 204.8M·年老代 = 1024M/5*4 = 819.2M如果-Xms和-Xmx的值設(shè)置的不一樣,可以添加 -XX:MinHeapFreeRatio=<minimum> 和 -XX:MaxHeapFreeRatio=<maximum> 參數(shù),使內(nèi)存的大小能夠在 大于 -Xms 和 小于 -Xmx 之間的范圍內(nèi)自動調(diào)整,所以內(nèi)存中會有Virtual的空間(我是這樣理解的,不是太清楚,這里需要大家指教)英文原文如下:http://java.sun.com/docs/hotspot/gc1.4.2/#3. Sizing the Generations|outlineBy default, the virtual machine grows or shrinks the heap at each collection to try to keep the proportion of free space to live objects at each collection within a specific range. This target range is set as a percentage by the parameters -XX:MinHeapFreeRatio=<minimum> and -XX:MaxHeapFreeRatio=<maximum>, and the total size is bounded below by -Xms and above by -Xmx .
-XX:SurvivorRatio=4:設(shè)置年輕代中Eden區(qū)與Survivor區(qū)的大小比值。設(shè)置為4,則兩個Survivor區(qū)與一個Eden區(qū)的比值為2:4,一個Survivor區(qū)占整個年輕代的1/6
-XX:MaxPermSize=16m:設(shè)置持久代大小為16m。
-XX:MaxTenuringThreshold=0:設(shè)置垃圾最大年齡。如果設(shè)置為0的話,則年輕代對象不經(jīng)過Survivor區(qū),直接進(jìn)入年老代。對于年老代比較多的應(yīng)用,可以提高效率。如果將此值設(shè)置為一個較大值,則年輕代對象會在Survivor區(qū)進(jìn)行多次復(fù)制,這樣可以增加對象再年輕代的存活時間,增加在年輕代即被回收的概論。
總結(jié)如下圖:
- Partial GC:并不收集整個GC堆的模式
- Young GC:只收集young gen的GC
- Old GC:只收集old gen的GC。只有CMS的concurrent collection是這個模式
- Mixed GC:收集整個young gen以及部分old gen的GC。只有G1有這個模式
- Full GC:收集整個堆,包括young gen、old gen、perm gen(如果存在的話)等所有部分的模式。
Major GC通常是跟full GC是等價的,收集整個GC堆。但因為HotSpot VM發(fā)展了這么多年,外界對各種名詞的解讀已經(jīng)完全混亂了,當(dāng)有人說“major GC”的時候一定要問清楚他想要指的是上面的full GC還是old GC。
對于 Hotspot 中常見的收集器 :serial GC, ?parallel GC, CMS(concurrent Mark Sweep),G1(garbage first garbage collector)這是收集器算法,就是選擇何時觸發(fā)minor GC,和 full GC.
比如:
serial GC單線程 收集器,它要是執(zhí)行,那么應(yīng)用線程都得終止。觸發(fā)條件:
Minor GC的過程:
?1)新生成的對象在Eden區(qū)完成內(nèi)存分配?2)當(dāng)Eden區(qū)滿了,再創(chuàng)建對象,會因為申請不到空間,觸發(fā)minorGC,進(jìn)行young(eden+1survivor)區(qū)的垃圾回收。(為什么是eden+1survivor:兩個survivor中始終有一個survivor是空的,空的那個被標(biāo)記成To Survivor)?3)minorGC時,Eden不能被回收的對象被放入到空的survivor(也就是放到To Survivor,同時Eden肯定會被清空),另一個survivor(From Survivor)里不能被GC回收的對象也會被放入這個survivor(To Survivor),始終保證一個survivor是空的。(MinorGC完成之后,To Survivor 和 From Survivor的標(biāo)記互換)?4)當(dāng)做第3步的時候,如果發(fā)現(xiàn)存放對象的那個survivor滿了,則這些對象被copy到old區(qū),或者survivor區(qū)沒有滿,但是有些對象已經(jīng)足夠Old(通過XX:MaxTenuringThreshold參數(shù)來設(shè)置),也被放入Old區(qū)?5)當(dāng)Old區(qū)被放滿的之后,進(jìn)行完整的垃圾回收,即 Full GC?6)Full GC時,整理的是Old Generation里的對象,把存活的對象放入到Permanent Generation里。--串行(–XX:+UseSerialGC )Out of Box算法,年輕代串行復(fù)制,年老代串行標(biāo)記整理,主要用于桌面應(yīng)用
--并行(–XX:+UseParallelGC )年輕代暫停應(yīng)用程序,多個垃圾收集線程并行的復(fù)制收集,年老代暫停應(yīng)用程序,與串行收集器一樣,單垃圾收集線程標(biāo)記整理。JDK 6.0啟用該算法后,默認(rèn)啟用了-XX:+UseParallelOldGC,性能大為提高
--并發(fā)(Concurrent Low Pause Collector)( –XX:+UseConcMarkSweepGC )啟用該參數(shù),默認(rèn)啟用了-XX:+UseParNewGC;簡單的說,并發(fā)是指用戶線程與垃圾收集線程并發(fā),程序在繼續(xù)運行,而垃圾收集程序運行于其他CPU上。
---目前客戶端應(yīng)用程序采用上述兩種收集器。服務(wù)器端一般采用CMS 和 G1垃圾收集器,Java9 將默認(rèn)采用G1垃圾收集器。
這張圖來自于《深入理解Java虛擬機--jvm最高特性與最佳實踐 ? ?周志明》,這張圖也是很多Java初學(xué)者了解Hotspot GC需要記住了解的圖。下面 就說明一下圖中這些minor GC,先說serialNew 和 serialOld 這個是單線程的,也就是stop all of world,當(dāng)然其他的GC,比如parallelOld 和 parNew雖是多線程收集,但是還是stop the world.serialold 或者 serialNew 單線程,回收效率較低,那么為什么現(xiàn)在還在使用???那是因為其算法簡單,停止所有應(yīng)用線程去專心收集垃圾,收集效率極高,幾乎把你所有沒有使用到的對象垃圾都給你收回來。專心做收集,那么你的內(nèi)存空間能多大呢?還不得幾十毫秒或者幾百毫秒就給你搞定的事情。停頓也是極短的時間。所以這個垃圾回收器一直都在使用。在client程序中也是主導(dǎo)的。
parNew 和 parallel Old 垃圾回收器和serial很相近,無非就是使用了多線程,目的就是借助處理器的多核能力。(畢竟現(xiàn)在處理器都是多核的)
parallel Scavenge 這個較為特殊的GC,其目的是為了實現(xiàn)最大的吞吐量,吞吐量=用戶任務(wù)處理時間 / (用戶處理時間 + 垃圾回收時間);說白了我就是給用戶開口讓其設(shè)置參數(shù)來限制垃圾回收的時間,怎么限制垃圾回收時間,就是讓垃圾不是那么徹底的回收干凈,犧牲一定的yong 代空間,那么我讓你回收時間縮短,增加吞吐量。
CMS consurrent mark sweep 這個回收器是在old 代的,主要和其他yong代配合使用,上述圖中,只要垃圾回收器之間有連接線,那么就可以配合使用。CMS看其名稱就知道基于標(biāo)記-清除算法,標(biāo)記清除-清除算法,有好處,啥好處?就是省空間,不復(fù)制,不節(jié)省空間嘛。但是產(chǎn)生垃圾碎片,導(dǎo)致存儲空間不連續(xù)。有沒有好的垃圾清除算法(垃圾清除算法主要就是標(biāo)記算法,復(fù)制算法,標(biāo)記-清除算法,標(biāo)記整理算法),好的算法就是標(biāo)記-整理算法,但是復(fù)雜呀!!!CMS是要降低停頓時間,你搞個那么復(fù)雜的算法,回收時間咋控制。 CMS工作主要分為四個步驟,初始標(biāo)記--并發(fā)標(biāo)記--重復(fù)標(biāo)記--并發(fā)清除;初始標(biāo)記和重復(fù)標(biāo)記是stop the word,為啥??? 標(biāo)記的時候為了標(biāo)記的準(zhǔn)確同時對整個old空間都做標(biāo)記,應(yīng)用線程不得停頓嘛!并發(fā)標(biāo)記的時候是基于初始標(biāo)記的結(jié)果,所以用戶線程可以運行,所以這個過程是并發(fā)的。重復(fù)標(biāo)記是同一個道理,回收的時候,就是多線程并發(fā)回收。CMS在回收的時候由于分多個過程,回收時間也稍稍長,那么這個過程中,用戶線程并發(fā)性能回收影響。
在CMS收集垃圾的時候,會給用戶線程留點空間,用于用戶存儲old數(shù)據(jù),如果在垃圾回收的過程中,這塊小區(qū)域滿了,那么用戶線程都要被停止。
G1垃圾回收器,garbage first,就是講堆區(qū)劃分很多的區(qū)域塊,優(yōu)先回收優(yōu)先級較高的區(qū)域,而且會綜合之前回收的經(jīng)驗,統(tǒng)計便于收集或者這塊區(qū)域較為重要,或者垃圾較多的區(qū)域,對其優(yōu)先收集。而且在手機過程中,其他區(qū)域是可以提供給用戶開銷的,所以G1幾乎使得用戶線程不停頓。 三、Java內(nèi)存的調(diào)優(yōu)參數(shù)-Xmx1024m:設(shè)置JVM最大可用內(nèi)存為1024M。
-Xms1024m:設(shè)置JVM促使內(nèi)存為1024M。此值可以設(shè)置與-Xmx相同,以避免每次垃圾回收完成后JVM重新分配內(nèi)存。
-Xmn512m:設(shè)置年輕代大小為512M。(持久代一般固定大小為64m,所以增大年輕代后,將會減小年老代大小。此值對系統(tǒng)性能影響較大,Sun官方推薦配置為整個堆的3/8。)
-Xss128k:設(shè)置每個線程的堆棧大小。這個值可以根據(jù)應(yīng)用的線程所需內(nèi)存大小進(jìn)行調(diào)整。在相同物理內(nèi)存下,減小這個值能生成更多的線程。但是操作系統(tǒng)對一個進(jìn)程內(nèi)的線程數(shù)還是有限制的,不能無限生成。
-XX:NewRatio=4設(shè)置年輕代(包括Eden和兩個Survivor區(qū))與年老代的比值(總的大小是Xms的值)。設(shè)置為4,則年輕代與年老代所占比值為1:4,年輕代占整個堆棧的1/5。舉個例子,-Xms 設(shè)置為 1024m,-Xmx 也設(shè)置為 1024m的情況下:·年輕代 = 1024M/5 = 204.8M·年老代 = 1024M/5*4 = 819.2M如果-Xms和-Xmx的值設(shè)置的不一樣,可以添加 -XX:MinHeapFreeRatio=<minimum> 和 -XX:MaxHeapFreeRatio=<maximum> 參數(shù),使內(nèi)存的大小能夠在 大于 -Xms 和 小于 -Xmx 之間的范圍內(nèi)自動調(diào)整,所以內(nèi)存中會有Virtual的空間(我是這樣理解的,不是太清楚,這里需要大家指教)英文原文如下:http://java.sun.com/docs/hotspot/gc1.4.2/#3. Sizing the Generations|outlineBy default, the virtual machine grows or shrinks the heap at each collection to try to keep the proportion of free space to live objects at each collection within a specific range. This target range is set as a percentage by the parameters -XX:MinHeapFreeRatio=<minimum> and -XX:MaxHeapFreeRatio=<maximum>, and the total size is bounded below by -Xms and above by -Xmx .
-XX:SurvivorRatio=4:設(shè)置年輕代中Eden區(qū)與Survivor區(qū)的大小比值。設(shè)置為4,則兩個Survivor區(qū)與一個Eden區(qū)的比值為2:4,一個Survivor區(qū)占整個年輕代的1/6
-XX:MaxPermSize=16m:設(shè)置持久代大小為16m。
-XX:MaxTenuringThreshold=0:設(shè)置垃圾最大年齡。如果設(shè)置為0的話,則年輕代對象不經(jīng)過Survivor區(qū),直接進(jìn)入年老代。對于年老代比較多的應(yīng)用,可以提高效率。如果將此值設(shè)置為一個較大值,則年輕代對象會在Survivor區(qū)進(jìn)行多次復(fù)制,這樣可以增加對象再年輕代的存活時間,增加在年輕代即被回收的概論。
總結(jié)如下圖:
總結(jié)
以上是生活随笔為你收集整理的Minor GC,Major GC,Full GC -- hotspot VM GC讲解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Pytorch官网一直很卡进不去,离线下
- 下一篇: android 全局对话框(不依赖具体a