JVM 調優理論知識:垃圾回收。常見垃圾回收器、GC算法。PC、PN、CMS、PO、G1、ZGC

 

熟悉GC常用算法,熟悉常見垃圾收集器,具有實際JVM調優實戰經驗

garbage : 垃圾

什麼是garbage?沒有被引用的對象都是垃圾 garbage

how to find a garbage  如何找到垃圾

1.reference count  引用計數

rc 不能解決的問題: 循環引用。例如 A引用B,B引用C,C引用A.

2.root searching  根可達算法。根對象: 線程棧變量、靜態變量、常量池、JNI指針

GC algorithms   : GC 算法

1. Mark-Sweep ( 標記清除 )

2.Copying (拷貝)

3. Mark-Compact (標記壓縮)

 

Mark-Sweep ( 標記清除 ):算法相對簡單,在存活對象比較多的情況下效率較高。兩遍掃描,效率較低,容易產生碎片。

不適合Eden 區

 

Copying:適用於存活對象較少的情況,只掃描一次,效率提高,沒有碎片。 空間浪費,移動複製對象,需要調整對象引用。

適合於 Eden 區

 

Mark-Compact (標記壓縮):不會產生碎片,方便對象分配,不會產生內存減半。需要掃描兩次,需要移動對象,效率偏低

 

 一個對象如果 stack(棧)上分配足夠,如果扔不下,直接扔到eden區。

 

 

 對象什麼時候進入老年代

Eden區+s1 放到s2 ,如果超過50%,則優先將年齡大的對象放入到老年代。

 

對象分配過程

 1.new 對象,判斷對象在stack(棧)裏面是否放的下,放的下就放,用完銷燬,結束。

2.  棧分配不下,看下大小(可通過參數設置),比較大,直接進入old區。進行了FGC纔會結束。

3. 如果不夠大,會進入到TLAB,即進入Eden區。

4. 如果被GC清除,則結束。如果沒被GC清除,則進入s1。

5. s1再進行清除。如果年齡夠了,則進入到老年代,不夠則進入s2,s2再進行gc清除,沒被清除進入到s1,知道年齡足夠進入老年代

6.當遭遇老年代FGC時被清除,則end。

 

常見垃圾回收器

1. JDK誕生 Serial追隨 提高效率,誕生了PS,爲了配合CMS,誕生了PN,CMS是1.4版本後期引入,CMS是里程碑式的GC,它開啓了併發回收的過程,但是CMS毛病較多,因此目前任何一個JDK版本默認不是CMS
   併發垃圾回收是因爲無法忍受STW
2. Serial 年輕代 串行回收
3. PS 年輕代 並行回收
4. ParNew 年輕代 配合CMS的並行回收
5. SerialOld  單線程
6. ParallelOld
7. ConcurrentMarkSweep 老年代 併發的, 垃圾回收和應用程序同時運行,降低STW的時間(200ms)
   CMS問題比較多,所以現在沒有一個版本默認是CMS,只能手工指定
   CMS既然是MarkSweep,就一定會有碎片化的問題,碎片到達一定程度,CMS的老年代分配對象分配不下的時候,使用SerialOld 進行老年代回收
   想象一下:
   PS + PO -> 加內存 換垃圾回收器 -> PN + CMS + SerialOld(幾個小時 - 幾天的STW)
   幾十個G的內存,單線程回收 -> G1 + FGC 幾十個G -> 上T內存的服務器 ZGC
   算法:三色標記 + Incremental Update
8. G1(10ms)
   算法:三色標記 + SATB
9. ZGC (1ms) PK C++
   算法:ColoredPointers(顏色指針) + LoadBarrier
10. Shenandoah
    算法:ColoredPointers(顏色指針) + WriteBarrier
11. Eplison
12. 垃圾收集器跟內存大小的關係
    1. Serial 幾十兆
    2. PS 上百兆 - 幾個G
    3. CMS - 20G
    4. G1 - 上百G
    5. ZGC - 4T - 16T(JDK13)

1.8默認的垃圾回收:PS + ParallelOld

常用組合:  serial + serial old、parallel scavenge + parallel old 、parnew + cms。

STW : stop-the-world 。停止一切

 

常用垃圾回收器圖、JVM內存分代模型(用於分代垃圾回收算法)

 

serial  + serial old  單線程回收。及除垃圾回收器工作外,其它線程都暫停。

serial old 同serial ,也是單線程的,只不過用在老年代

 

 

PS:parallel (並行)scavenge   多線程同時清理

 

parnew  parallel 的新版本,但是可以配合 CMS使用。例如:cms 某個特定階段時 ,parnew可以同時運行。

 

CMS: concurrent mark sweep

concurrent(併發)。應用可以一邊工作,垃圾回收器可以一邊進行。

cms 清理的4個階段:

1. 初始標記 ,只標記根對象。STW過程。 -- initial mark

2. 併發標記, 併發標記可以和應用程序同時運行。 -- concurrent mark

3. 重新標記,對併發標記過程中產生的垃圾進行標記,STW過程。 -- remark

4. 併發清理,進行垃圾清理。 -- concurrent sweep

老年代分配不下了久會促發 cms

cms缺點:

1. Memory Fragmentation   內存碎片化

   > -XX:+UseCMSCompactAtFullCollection
   > -XX:CMSFullGCsBeforeCompaction 默認爲0 指的是經過多少次FGC才進行壓縮
   

2. Floating Garbage  浮動垃圾

   > Concurrent Mode Failure
   > 產生:if the concurrent collector is unable to finish reclaiming the unreachable objects before the tenured generation fills up, or if an allocation cannot be satisfiedwith the available free space blocks in the tenured generation, then theapplication is paused and the collection is completed with all the applicationthreads stopped
   >
   > 解決方案:降低觸發CMS的閾值。-XX:CMSInitiatingOccupancyFraction 92% 可以降低這個值,讓CMS保持老年代足夠的空間. 默認設置爲92%產生FGC,可以通過降低預值例如:68%、 50%等等 來保證有足夠的空間進行分配
   >
  > PromotionFailed 內存分配錯誤
  > 解決方案類似,保持老年代有足夠的空間

浮動垃圾和內存碎片化都會導致從年輕代過來的對象會找不到可足夠分配的空間,需要使用 serial old 進行清理, 造成STW 時間較長。

Full GC : 整體內存。 觸發條件:老年代內存不夠就會觸發。默認PS + PO,或者PN+CMS


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章