文章目錄
- 分代收集算法
- 引用計數算法
-
- 優點
- 缺點
- 标記清除法
-
- 缺點
- 複制算法
-
- 優點
- 缺點
- 标記壓縮算法
-
- 優點
想要做好JVM參數調優,是需要對GC的機制以及算法有所了解,掌握GC原理後根據具體的需求對JVM進行優化,可以有效減少GC的次數,進而提高程式的效率。
為什麼要GC的次數多了會影響性能呢,因為每當GC執行是,所有的線程将會被暫停,這個暫停就是導緻性能降低的關鍵因素,而且GC本身運作也是消耗資源的。
垃圾回收的任務是識别和回收垃圾對象進行記憶體清理,為了讓垃圾回收器可以更高效的執行,大部分情況下,會要求系統進如一個停頓的狀态。停頓的目的是為了終止所有的應用線程,隻有這樣的系統才不會有新垃圾的産生。同時停頓保證了系統狀态在某一個瞬間的一緻性,也有利于更好的标記垃圾對象。是以在垃圾回收時,都會産生應用程式的停頓。
每種GC算法都有各自的優缺點,以下列舉的幾個算法:
分代收集算法
根據記憶體中對象的存活周期不同,将記憶體劃分為幾塊,java的虛拟機中一般把記憶體劃分為新生代和年老代,當新建立對象時一般在新生代中配置設定記憶體空間,當新生代垃圾收集器回收幾次之後仍然存活的對象會被移動到年老代記憶體中,當大對象在新生代中無法找到足夠的連續記憶體時也直接在年老代中建立。
對于新生代和老年代來說,新生代回收頻率很高,但是每次回收耗時很短,而老年代回收頻率較低,但是耗時會相對較長,是以應該盡量減少老年代的GC。
引用計數算法
給對象中添加一個引用計數器,每當有一個地方引用它時,計數器值就加1;當引用失效時,計數器值就減1;任何時刻計數器都為0的對象就是不再被使用的,垃圾收集器将回收該對象使用的記憶體。
優點
引用計數收集器可以很快的執行,交織在程式運作中。對程式需要不被長時間打斷的實時環境比較有利。
缺點
無法檢測出循環引用。如父對象有一個對子對象的引用,子對象反過來引用父對象。這樣,他們的引用計數永遠不可能為0.而且每次加減非常浪費記憶體。
标記清除法
标記-清除(Mark-Sweep)算法顧名思義,主要就是兩個動作,一個是标記,另一個就是清除。
标記就是根據特定的算法(如:引用計數算法,可達性分析算法等)标出記憶體中哪些對象可以回收,哪些對象還要繼續用。
标記訓示回收,那就直接收掉;标記訓示對象還能用,那就保留在原先的記憶體位址不變。
缺點
- 标記與清除效率低。
- 清除之後記憶體會産生大量碎片,還需要有住啊們的清理随便的算法對這些随便進行處理,進一步的消耗資源。
複制算法
複制算法是使用在新生代中的垃圾回收算法。
jvm的記憶體結構中,将堆記憶體分為了新生代和老年代兩個部分。建立出的對象(如:new 出的對象)會先進入新生代,如果該對象多次(JVM預設是15次)GC後未被回收,則會将對象轉存到老年代。可以了解為,新生代存儲的是使用後很快就會被回收的對象,老年代存儲的是長期在使用的對象。
将可用記憶體按容量分成大小相等的兩塊,每次隻使用其中一塊,當這塊記憶體使用完了,就将還存活的對象複制到另一塊記憶體上去,然後把使用過的記憶體空間一次清理掉。
形象一點的比喻:
就好比如,将一塊硬碟分成D盤和E盤兩個分區,每次隻使用一個分區,比如先使用D盤,使用一段時間以後當需要做磁盤清理的時候,就将D盤中需要保留的檔案拷貝到E盤中,然後再将D盤格式化(很霸道,很粗暴,但是清理的很幹淨)。在下一次清理之前,一直都是使用E盤,直到清理E盤以後,又回到使用D盤,如此的循化。總結就是兩個步驟 複制 和 格式化(清除)
優點
每次都是對其中一塊記憶體進行回收,記憶體配置設定時不用考慮記憶體碎片等複雜情況,隻需要移動堆頂指針,按順序配置設定記憶體即可,實作簡單,運作高效。
缺點
因為将記憶體劃分成了兩塊一樣大大小,所有可使用的記憶體降為原來一半。
标記壓縮算法
标記壓縮算法是使用在老年代中的垃圾回收算法。
标記壓縮算法,是在标記清除法之上進行了優化。執行完标記以後,
- 1.先将存活的對象壓縮到了記憶體的一端,被标記要清除的對象壓縮到記憶體的另外一端。
- 2.如此一來,所有存活的對象的記憶體位址是連續的,将被清除的對象記憶體位址也是連續的,就好像一根繩子被劃分成了兩個部分一樣。
- 3.将所有要被清除的對象的位址全部釋放。
優點
- 不會留下碎片,所有的對象存儲具有連續性。
- 清理的算法簡單,執行效率高。
标記壓縮算法 與 複制算法 非常的相識,但是卻完全不一樣。差別在于,複制算法會将記憶體分為兩個相等的塊,而标記壓縮算法則沒有将記憶體分塊。