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