詳解GC回收機制

GC回收是按照五種算法實現的

1.引用計數算法

   效率較高,但是無法回收循環引用的對象

2.根搜索算法

   它的處理方式就是,設立若干種根對象,當任何一個根對象到某一個對象均不可達時,則認爲這個對象是可以被回收的

   GC root有幾下種:

  • Class - 由系統類加載器(system class loader)加載的對象,這些類是不能夠被回收的,他們可以以靜態字段的方式保存持有其它對象。我們需要注意的一點就是,通過用戶自定義的類加載器加載的類,除非相應的java.lang.Class實例以其它的某種(或多種)方式成爲roots,否則它們並不是roots,.
  • Thread - 活着的線程
  • Stack Local - Java方法的local變量或參數
  • JNI Local - JNI方法的local變量或參數
  • JNI Global - 全局JNI引用
  • Monitor Used - 用於同步的監控對象
  • Held by JVM - 用於JVM特殊目的由GC保留的對象,但實際上這個與JVM的實現是有關的。可能已知的一些類型是:系統類加載器、一些JVM知道的重要的異常類、一些用於處理異常的預分配對象以及一些自定義的類加載器等。然而,JVM並沒有爲這些對象提供其它的信息,因此需要去確定哪些是屬於"JVM持有"的了。

3.標記/清除算法

       標記:標記的過程其實就是,遍歷所有的GC Roots,然後將所有GC Roots可達的對象標記爲存活的對象。

       清除:清除的過程將遍歷堆中所有的對象,將沒有標記的對象全部清除掉。

       這種算法的缺點就是效率比較低且清理出來的空閒內存是不連續的

4.複製算法

     複製算法將內存劃分爲兩個區間,在任意時間點,所有動態分配的對象都只能分配在其中一個區間(稱爲活動區間),而另

     外一個區間(稱爲空閒區間)則是空閒的。

     當有效內存空間耗盡時,JVM將暫停程序運行,開啓複製算法GC線程。接下來GC線程會將活動區間內的存活對象,全部

     複製到空閒區間,且嚴格按照內存地址依次排列,與此同時,GC線程將更新存活對象的內存引用地址指向新的內存地址。

     此時,空閒區間已經與活動區間交換,而垃圾對象現在已經全部留在了原來的活動區間,也就是現在的空閒區間。事實上,

     在活動區間轉換爲空間區間的同時,垃圾對象已經被一次性全部回收。

     這種算法的缺點就是內存消耗大,浪費了一半的內存

5.標記/整理算法

    標記:它的第一個階段與標記/清除算法是一模一樣的,均是遍歷GC Roots,然後將存活的對象標記。

   整理:移動所有存活的對象,且按照內存地址次序依次排列,然後將末端內存地址以後的內存全部回收。因此,第二階段 

   才稱爲整理階段。 

   標記/整理算法唯一的缺點就是效率也不高

總結:

後面三種算法是根據根搜索算法判斷是否應該被回收,而支撐根搜索算法可以正常工作的理論依據,就是語法中變量作用域的相關內容。因此要想防止內存泄露,最根本的辦法就是掌握好變量作用域。 

 

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