1. 程式人生 > >JVM GC演算法以及調優

JVM GC演算法以及調優

jvm的垃圾回收器是jvm的重要組成部分。GC負責著整個jvm執行時堆中物件的回收,保證jvm的效能。由於Java執行GC垃圾回收時會阻塞其他所有的執行緒,這樣是對使用者極不友好的,即對GC的優化重點是降低阻塞的時間,對GC的調優也就是對jvm的效能調優的重點。

jvm堆的記憶體模式(畫的比較簡陋,忘海涵)
這裡寫圖片描述

jvm為堆記憶體劃分了幾塊區域如上圖:
最左邊的new generation是新生代,新生代分為3塊區域一個是eden區,還有兩個suvivor區。最右邊的是老年代區域。

例項化一個物件時
1. 絕大多數剛剛被建立的物件會存放在eden空間。
2. 在eden空間執行了第一次GC之後,存活的物件被移動到其中一個survivor空間。
3 .此後,在eden空間執行GC之後,存活的物件會被堆積在同一個survivor空間。
4. 當一個survivor空間飽和,還在存活的物件會被移動到另一個survivor空間。之後會清空已經飽和的那個survivor空間。
5. 在以上的步驟中重複幾次依然存活的物件,就會被移動到老年代。

從上面執行過程可以看出survivor區域必定有一塊是空的,用JVM監控工具可以觀察兩個survivor區域的狀況,如果兩個survivor區域都有物件,則說明此時jvm是有問題的。

GC常用演算法:

  1. 序列收集器(Serial GC)
    最古老的垃圾回收演算法沒有之一,是以前執行在單核cpu的伺服器下 的。新生代、老年代都使用序列演算法回收。
    演算法的第一步是標記老年代中依然存活物件。第二步是從頭開始檢查堆記憶體空間,並且只留下依然倖存的物件。最後一步,從頭開始,順序地填滿堆記憶體空間,並且將對記憶體空間分成兩部分:一個儲存著物件,另一個空著。

    在jvm下配置的引數是 -XX:+UseSerialGC

  2. 並行垃圾回收器(Parallel GC)
    parallel GC可以看成是Serial GC的升級版,它是採用多執行緒的機制是執行GC操作,所以執行GC過程阻塞時間較短。新生代採用的是並行演算法,而老年代依然採用的是序列演算法。

    在jvm下配置的引數是 -XX:+UseParallelGC,是jvm預設的GC回收演算法。這裡寫圖片描述

  3. 併發標記掃描垃圾回收器(CMS收集器)
    Concurrent Mark Sweep是應用程式執行緒和GC執行緒交替執行
    使用的標記-清除演算法,併發階段會降低吞吐量。它經常被用在那些對於響應時間要求十分苛刻的應用之上。
    老年代收集器。

    在jvm下配置的引數是 -XX:+UseConcMarkSweepGC

  4. G1收集器
    G1垃圾回收器適用於堆記憶體很大的情況,他將堆記憶體分割成不同的區域,並且併發的對其進行垃圾回收。G1也可以在回收記憶體之後對剩餘的堆記憶體空間進行壓縮。併發掃描標記垃圾回收器在STW情況下壓縮記憶體。G1垃圾回收會優先選擇第一塊垃圾最多的區域.

    在jvm下配置的引數是 -XX:+UseG1GC

根據應用場景的不同選擇不同的GC演算法是必要的。還有一些重要的引數,例如分配給堆的記憶體大小最大是多少 -Xmx引數,初始化是多少-Xms,一般我們將-Xmx與-Xms設定相同,避免jvm頻繁的變更堆記憶體的大小消耗cpu的效能;還有新生代的區域大小引數的配置-XX:NewRatio:3,一般配置的是2-3,這時新生代的記憶體大小=Xmx/NewRatio+1。

一般推薦的JVM引數
這裡寫圖片描述