G1
解決的問題G1
垃圾回收器是04
年正式提出,12
開始正式支持,在17
年做爲JDK9
默認的垃圾處理器。
java
在04
年的時候,java
程序堆的內存愈來愈大,從而致使程序中可存活的活對象愈來愈多,所以GC
的STW
時間愈來愈長。這是G1
要解決的主要問題:STW
帶來的停頓時間太長了。算法
CMS
在此以前效率也很高,但活對象數量一多,STW
時間也很長。並且CMS
沒法解決內存碎片化的問題。shell
G1
還解決的問題是:CMS
在GC
後,沒法compact
內存。多線程
G1
達成的目標(1)減小因爲STW
而帶來的程序延遲時間,作到僞實時、低延時、可設定目標;
可設定目標是指可以設置GC
最大STW
停頓的時間,G1
會盡可能達成目的,但不必定達成。併發
-XX:MaxGCPauseMillis=N
默認狀況下是250毫秒oracle
(2)解決CMS
在GC
後,沒法壓縮程序內存的問題;app
(3)在JDK9
以後,默認的垃圾處理器就是G1
;它適用於堆內存較大的狀況下(>4~6G
);佈局
G1
垃圾回收器G1
內存佈局G1
再也不遵循以前的堆中對象的分代排列,而是將堆分紅若干個等大的區域。
線程
而是變成:
3d
默認是分紅
2048
個區域,-XX:G1HeapRegionSize=N 2048
Humongous
:當你分配的一個對象超過一半區域的大小時,這個對象就會被放入這個區域。這個區域屬於老年代區域。
G1
的介紹G1
垃圾回收器再也不回收整個堆,而是選擇一個Collection Set
(CS
)。並且每次GC
時,會估計每一個Region
中的垃圾比例,優先回收垃圾多的Region
。這就爲何被叫作Garbage First
算法。這也是爲何G1
能夠控制STW
停頓時間的緣由。
G1
含有三種GC
算法:
Full young GC
:年輕代GC
算法:STW
、Parallel
、Copying
GC
算法:Mostly-concurrent marking
、Incremental compaction
Mixed GC
:混合GC
G1
引來的問題G1
將年輕代、老年代區域劃分爲許多個小區域,增長在GC
判斷對象是否爲垃圾的難度。好比:
Region
間的互相引用假設在Full young GC
時,某個年輕代Region
對象可能被老年代的某個對象引用,那麼我在回收這個年輕代Region
時,怎麼知道這裏面的對象是否被其餘Region
、老年代引用呢?
Remembered Set
、Card Table
一、CardTable
每一個Region
中分爲不少區域,每一個區域咱們成爲CardTable
,對應的就是上述藍色區域;每一個CardTable
有多個entry
組成。當對應的內存空間發生改變時,就會標記爲dirty
。
二、RememberedSet
當Region1
的CardTable
引用Region2
的CardTable
時,Region2
的RememberedSet
就會記錄對應CardTable
中的entry
,能夠根據其找到對應的內存區域。
三、解析
當某個內存對應進行賦值是,就是對象的set
方法,咱們能夠在這種方法上添加dirty
的描述。
這其實就是典型的時間換空間的作法:用額外的空間維護引用信息,這就是佔用5~10%
的過多內存佔用。
一、Write Barrier
介紹
Write barrier
是一種向JVM
注入的一小段代碼,用於記錄指針變化。好比說object.field = <reference>
。
在JVM
開始更新指針時,就通過如下幾步:
Card
爲Dirty
Card
存入Dirty Card Queue
隊列中這裏有一個問題:爲何要放在隊列裏,而不是直接去更新RememberedSet
呢?
這是由於JVM
運行可能會有多個線程並行的修改RememberedSet
,這樣就須要花費額外的時間來解決多線程同步問題。而這種更新引用是頻繁的,因此這種額外時間是沒法忍受的。
二、Dirty Card Queue
這個隊列有白、綠、黃、紅四個顏色,表示應用線程往這個隊列聽任務的狀態。
White
表示沒有應用線程往隊列裏聽任務,什麼事都不用幹。
Green
此時Refinement
線程開始被激活,開始更新RS
。-XX:G1ConcRefinementGreenZone=N
Yellow
此時所有的Refinement
線程都被激活,來更新RS
。-XX:G1ConcRefinementYellowZone=N
Red
這個時候,應用線程也開始參與排空隊列的工做。-XX:G1ConcRefinementRedZone=N
GC
算法的過程Fully young GC
GC
的過程(1)STW
此時會暫停全部堆中的對象,將部分Region
拷貝到指定區域。
(2)構建Collection Set
fully young GC
就是選取全部的Eden
和Survivor
。
(3)掃描GC Roots
(4)更新RememberedSet
排空Dirty Card Queue
(5)Process RS
根據RS
找到要GC
的對象被哪些對象引用了。
(6)對象拷貝
survivor
區域對象的調整。
(7)Reference Processing
G1
記錄每一個階段的時間,用於後期自動調優。好比說會記錄Eden
、Survivor
的數量和GC
時間,後期會根據咱們以前設定的暫停目標來自動調整Region
數量。
可是咱們設置暫停目標越短,年輕代的Region
數量就越少。但這可能會致使Fully young GC
頻繁發生。
Old GC
當堆用量達到必定程度時,就會觸發old GC
。能夠經過如下參數進行設置:
-XX:InitatingHeapOccpancyPercent=45
old GC
有一個很大特色就是併發進行的。但它是如何在堆中不斷變化的狀況下,肯定哪些是要清理的垃圾對象呢?
這種算法實現了在不暫停應用線程的狀況下進行併發標記,標記過程過以下:
(1)將GC Root
對象記錄爲黑色,其直接引用對象記錄爲灰色,並將這些灰色對象放入一個隊列中
(2)從隊列取出對象,將其標爲黑色,將其引用對象記錄爲灰色,再放入隊列中
(3)直到隊列中無對象爲止
Lost Object Problem
三色標記算法並無徹底將全部的活對象都標記出來,這就是Lost Object Problem
問題。好比說:
(1)剛開始時
(2)在即將描述將C
標爲灰色的一剎那
此時,C
依然是活對象,可是已經沒法將其標記了。
(3)結果
Lost Object Problem
的解決這種解決辦法仍是經過Write barrier
技術來解決。當B.c=null
,也就是C
指針被刪除時,G1
仍是被認爲活對象。
那若是
C
是新生對象呢?這是老年代GC
Old GC
過程(1)STW
老年代GC
會在這個時候,進行一次Fully young GC
(2)恢復應用線程
(3)使用三色標記算法併發標記(init marking
)
(4)STW
這時候會有一個Remark
階段,主要是解決SATB
、Reference processing
還會有一個Cleanup
階段,用於回收全爲空的區
(5)恢復應用線程
Mixed GC
咱們直到CMS
最大的缺點就是沒法進行壓縮操做,而G1
就經過Mixed GC
解決了這個問題。
Mixed GC
沒有固定觸發條件,他是根據Fully young GC
收集的信息和咱們配置的時間來決定,是否觸發Mixed GC
。它會根據暫停目標,來優先選擇垃圾最多的Old Region
來執行。
Mixed GC
會選擇若干個Region
進行,默認是選擇1/8
的Old Region
、Eden Region
、Survivor Region
。
Mixed GC
的過程跟Fully young GC
的過程相同,都是:STW
、Parallel
、Copying
。