GC算法和種類

GC的概念

Garbage Collection 垃圾收集,簡稱GC。Java中GC的對象是堆空間和永久區。
複製代碼

GC算法

引用計數法
  • 概念:引用計數法是老牌的垃圾回收算法了,經過對象的引用來計算要不要回收,com、ActionScript三、python 都使用過。
  • 原理:對於一個對象A,只要任何一個對象引用,則A的引用計數器就加1,若是取消引用就減一。若是計數器爲零這個對象就是垃圾
  • 缺點:引用和去除引用伴隨着加法減法,影響性能。還有就是很難處理循環引用(看下圖)。
  • 優勢:即時回收,由於對象知道本身何時沒用
標記清除
  • 概念:標記——清除算法是現代垃圾回收算法的思想基礎。
  • 原理:這個算法將垃圾回收分爲了兩個階段,標記階段和清除階段。一種可行的實現是,在標記階段,首先經過根節點,標記全部從根節點開始可達對象。所以未標記的對象就是未被引用的垃圾對象。而後在清除階段,清除未被標記的對象。(看下圖)
  • 缺點:逐漸產生被細化的分塊,不久後就會致使無數的 小分塊散佈在堆的各處。這個內存就會被分的七零八落的,這樣在分配對象的時候還得先遍歷那些內存塊能夠用。
  • 優勢:實現起來簡單
標記壓縮
  • 概念:標記-壓縮算法適合用於存活對象較多的場合,如老年代。它在標記-清除算法的基礎上作了一些優化
  • 原理:和標記清除同樣,先標記可是以後清除操做的時候將全部存活的對象壓縮到內存的一端,而後清理這個邊界外的全部空間
  • 缺點:清除算法中,清除階段也要搜索整個堆,不過搜索 1 次就夠了。但 GC 標記 - 壓縮算法要搜索 3 次,這樣就要花費約 3 倍的時間,這是一個至關巨大的缺陷,特別是堆越 大,所消耗的成本也就越大(看圖)
  • 優勢:堆利用效率高。 並且 GC 標記 - 壓縮算法不會出現 GC 複製算法那樣只能利用半個堆的狀況
複製算法
  • 概念:在標記清除的的基礎上改進python

  • 原理:將原有的內存空間分爲兩塊,每次只使用其中一塊,在垃圾回收時,將正在使用的內存中的存活對象複製到未使用的內存塊中,以後,清除正在使用的內存塊中的全部對象,交換兩個內存的角色,完成垃圾回收算法

  • 缺點:看圖bash

  • 優勢:ide

    一、優秀的吞吐量: GC 標記 - 清除算法消耗的吞吐量是搜索活動對象(標記階段)所花費的時間和搜索總體 堆(清除階段)所花費的時間之和。  
     另外一方面,由於 GC 複製算法只搜索並複製活動對象,因此跟通常的 GC 標記 - 清除算 法相比,它能在較短期內完成 GC。也就是說,其吞吐量優秀。
    
    二、高速分配:GC 複製算法不使用空閒鏈表。這是由於分塊是一個連續的內存空間。比起 GC 標記 - 清除算法和引用計數法等使用空閒鏈表的分配,GC 複製算法明顯快得多。
    
    三、不會發生碎片化
    複製代碼
GC算法總結

總結的時候我以爲仍是引入一下分代思想比較清晰post

依據對象的存活週期進行分類,短命對象歸爲新生代,長命對象歸爲老年代。性能

根據不一樣代的特色,選取合適的收集算法優化

  • 少許對象存活,適合複製算法
  • 大量對象存活,適合標記清理或者標記壓縮

可觸及性

問:GC算法中 怎麼判斷這個對象是不是垃圾對象,是根據可觸及性來判斷的,那麼什麼是可觸及性呢。ui

答:this

  • 棧中引用的對象
  • 方法區中靜態成員或者常量引用的對象(全局對象)
  • JNI方法棧中引用對象

還有一個概念也不能斷定這個對象是垃圾對象就是 --可復活的spa

一旦全部引用被釋放,就是可復活狀態,由於在finalize()中可能復活該對象
複製代碼

不過這個通常不使用:

避免使用finalize(),操做不慎可能致使錯誤。
 優先級低,什麼時候被調用, 不肯定
 什麼時候發生GC不肯定
 可使用try-catch-finally來替代它經驗:避免使用finalize(),操做不慎可能致使錯誤。 
 優先級低,什麼時候被調用, 不肯定
 什麼時候發生GC不肯定
 可使用try-catch-finally來替代它
複製代碼

這裏你能夠代碼試下

public class CanReliveObj {
   public static CanReliveObj obj;
   @Override
   protected void finalize() throws Throwable {
       super.finalize();
       System.out.println("CanReliveObj finalize called");
       obj=this;
   }
   @Override
   public String toString(){
       return "I am CanReliveObj";
   }


public static void main(String[] args) throws
    InterruptedException{
obj=new CanReliveObj();
obj=null;   //可復活
System.gc();
Thread.sleep(1000);
if(obj==null){
   System.out.println("obj 是 null");
}else{
   System.out.println("obj 可用");
}
System.out.println("第二次gc");
obj=null;    //不可復活
System.gc();
Thread.sleep(1000);
if(obj==null){
System.out.println("obj 是 null");
}else{
System.out.println("obj 可用");
}
}
複製代碼

Stop-The-World

詳情點擊 juejin.im/post/5d5a1b…

Java中一種全局暫停的現象,全局停頓,全部Java代碼中止,native代碼能夠執行,但不能和JVM交互,多半因爲GC引發 Dump線程、 死鎖檢查、堆Dump。

GC時爲何會有全局停頓? 類比在聚會時打掃房間,聚會時很亂,又有新的垃圾產生,房間永遠打掃不乾淨,只有讓你們中止活動了,才能將房間打掃乾淨。

危害:長時間服務中止,沒有響應,遇到HA系統,可能引發主備切換,嚴重危害生產環境。

相關文章
相關標籤/搜索