本系列文章屬於《JVM G1源碼分析和調優》讀書筆記。感謝做者的付出!java
G1概述和名詞解析
- G1特色:在知足短期停頓的同時,達到一個高的吞吐量,適用於多核處理器,大內存的系統。
-
短停頓時間且可控:算法
- G1對內存進行分區,基於部份內存回收的新生代收集和混合收集。
-
高吞吐量:緩存
- 優化GC工做,使其儘量與Mutator併發工做;
- 設計了新的併發標記線程,用於併發標記內存;
- 設計了Refine線程併發處理分區之間的引用關係
- FullGC:內存不足時,須要對所有內存(整個堆)進行垃圾回收,一般Full GC是串行的,G1的Full GC在JDK10以後有並行實現。
- 併發標記: G1新引入的,指Mutator運行的同時,標記哪些對象是垃圾。
- 傳統垃圾回收的實現邏輯:暫停一切活動(Stop the world),回收器完美的識別哪些對象有用,哪些無用。
- 併發標記的實現邏輯:在標記垃圾的時候,同時記錄系統增長了哪些對象,修改了哪些對象,增長了哪些垃圾等。在標記結束的時候,對這些發生過變動的對象從新標記一次 (再標記:remark)。固然,再標記須要STW,不然永遠沒有盡頭。這也被稱爲 增量併發標記,G1中具體的算法爲Snapshot-At-The-Beginging(SATB)。
- Refine線程:G1新引入的,在進行部分收集的時候加速識別活躍對象。
-
JVM中從新定義了併發和並行安全
- 並行:指多個垃圾回收相關線程在操做系統上併發運行。強調的只有垃圾回收線程工做,其餘的java 應用程序所有都暫停執行,所以parNew工做的時候必定發生STW(因此parNew被稱爲並行收集器)。
- 併發:指垃圾回收相關的線程併發運行,同時這些線程會和java應用程序併發運行。
- Stop-The-World(STW):中止一切,在JVM中中止一切java應用線程。
- 安全點(safepoint):線程並非在任何地方均可以進入stw,安全點是給線程提供一個能夠安全進入stw的位置。
- Mutator:特指java的應用線程。
- Remember Set(Rset)記憶集:主要記錄不一樣代際對象的引用關係。
- Evacuation(Evac): 在G1中指發現活躍對象,並將對象複製到新地址的過程。
- Reclaim 回收:一般指分區對象已經死亡或者完成Evac,分區能夠被jvm再次使用。
- Closure:閉包,提供對內存的訪問。
- GC Root:垃圾回收的根。垃圾回收過程當中,須要從GC Root出發標記活躍對象,確保正在使用的對象在垃圾回收後都是存活的。
- Root Set:在JVM的垃圾回收過程當中,須要從不一樣的GC Root出發,GC Root中包含有線程棧,monitor列表,JNI對象等,這些GC Root構成了Root Set。
回收算法概述
- 引用計數法:當堆內存分配對象時,額外分配一個空間維護計數器,增長一個新的引用,則增長計數器,若是引用關係失效,則減小計數器。當計數器爲0,則說明該對象已經被廢棄,能夠被回收。若是使用引用計數法,則有個循環依賴問題須要解決。
- 可達性分析法:將根集合作爲起點,從這些節點開始向下搜索,搜索所走過的路徑稱爲 引用鏈,當一個對象沒有被任何引用鏈訪問到時,則證實此對象是不活躍的,能夠被回收。
jvm採用可達性分析法
-
垃圾回收算法多線程
-
複製(copy)閉包
- 複製算法可使用多個分區,分區越多,利用率越大,例如,2個分區時,利用率爲50%,3個分區時,利用率能夠到66%
-
例如如今有3個分區 Eden,S0,S1併發
- 對象建立所有在Eden,S0,S1爲空
- 第一次垃圾回收:Eden和S0的存活對象經過複製算法拷貝到S1
- 第二次垃圾回收:Eden和S1的存活對象經過複製算法拷貝到S0
- 2,3不斷循環操做,全部新對象的建立所有在
- 缺點:堆的使用效率低 優勢:吞吐量大,沒有碎片,分配效率高
-
標記清除(Mark-Sweep)jvm
- 從根集合出發,遍歷對象,把活躍的對象入棧,依次處理。標記出活躍對象後,就能夠把剩餘的(不活躍的)對象清除。
- 缺點:內存碎片化 優勢:無需移動對象,算法簡單
-
標記壓縮(Mark-Compact)源碼分析
- 在完成標記清除的動做後,會把活躍對象從頭開始從新排列,以減小內存碎片
- 缺點:stw時間更長,對緩存不友好(對象移動後順序關係消失) 優勢:堆的使用效率高,無內存碎片
-
回收方法:優化
-
串行回收
- 使用單線程進行回收,mutator須要STW。一般新生代使用複製,老年代使用標記壓縮。
-
並行回收
- 使用多線程進行回收,mutator須要STW。一般新生代使用複製,老年代使用標記壓縮。(與串行回收不一樣在於,GC過程使用了多線程)
-
併發標記回收(CMS)
-
分爲多個階段
- 初始標記(STW)
- 併發標記
- 從新標記(STW)
- 併發清除
- 這個算法一般適用於老年代,新生代能夠採用並行回收。
-
垃圾優先回收(Garbage-First G1)
- 從JDK7U4開始提供
-
分區分爲
- 新生代分區
- 老年代分區:在任意時刻,只有部分老年代分區會被回收。這部分老年代分區會在下一次進行增量回收的時候同全部的新生代一塊兒被回收(混合回收)。在選擇老年代分區的時候,優先回收垃圾多的分區。
- 可用分區
- 大對象分區:對象大小超過必定的閾值以後,就再也不進行復制操做(複製時間過長),直接將對象分配到老年代中。
- G1將堆拆成一些列的分區(Heap Region),GC操做只針對一部分分區,而不是整個堆或者老年代。
- 新老代的分區的內存塊再也不須要連續,能夠互相轉化。新生代是並行收集,採用複製算法。
- G1 會根據預測時間動態改變新生代大小。
-
G1吸收了如下算法的優點:
- 列車算法:對內存進行分區
- CMS:併發標記回收
- 最老優先:最老的數據(越老的數據,是垃圾的可能性越高)優先收集。
-
內存管理
-
分代管理:假定內存分爲兩個代:新生代和老年代
- 新生代:容易死亡的對象放在新生代,一般採用複製算法
- 老年代:把預期活的時間長的對象放在老年代,一般使用標記清除算法
- 缺點:複雜 優勢:組合了算法,分配效率高,堆的使用率高
- 非分代管理