1. 程式人生 > >java垃圾回收機制的原理及優缺點

java垃圾回收機制的原理及優缺點

  優點:a.不需要考慮記憶體管理, b.可以有效的防止記憶體洩漏,有效的利用可使用的記憶體, c.由於有垃圾回收機制,Java中的物件不再有"作用域"的概念,只有物件的引用才有"作用域"

原理:垃圾回收器是作為一個單獨的低級別的執行緒執行,在不可知的情況下對記憶體堆中已死亡的或者長期沒有使用的物件回收,但是不能實時的對某一物件或者所有物件進行垃圾回收。

垃圾回收機制:分代複製垃圾回收、標記垃圾回收、增量垃圾回收

           GC(Gabage  Collection)工作原理:當建立物件時,GC就開始監視這個物件的地址、大小以及使用情況。通常,GC採用有向圖的方式記錄和管理heap(堆)中的素有物件。通過這種方式確定哪些物件是“可達的”,哪些是“不可以達的”。

      垃圾回收機制通常是作為一個單獨的低級別的執行緒執行,不可預知的情況下對記憶體堆中已經死亡的或者長時間沒有使用的物件進行清理,我們雖然可以呼叫System.gc()讓垃圾回收器執行,但依舊無法保證GC一定會執行。

           1.垃圾回收機制的目標是回收無用物件的記憶體空間(記住:不是物件),這些記憶體空間是JVM堆記憶體的記憶體空間。垃圾回收只回收記憶體資源,對於那些物理資源,如資料庫連線,Socket,I/O流等資源無能無能為力,我們要自己關閉回收。

    2.為了加快垃圾回收機制回收那些無用物件所佔的記憶體空間,我們可以講物件的引用變數置於null(記住:置於null後,垃圾回收機制不會立即執行的)。

    3.垃圾回收機制的潛在缺點它的開銷會影響效能。Java虛擬機器必須跟蹤程式中有用的物件才可以確定哪些物件時無用的,並釋放那些無用物件所佔的記憶體空間。這個過程要處花費處理器時間的。

    4.垃圾回收的不可預知性。我們可以通過Runtime物件的gc()方法或者System.gc()的方法來建議系統進行垃圾回收,但我們不能精確控制垃圾回收機制的執行。==================================================================================================

AVA垃圾回收機制(GC)簡單介紹

  • java中的垃圾回收機制(Garbage Collection, GC)使得我們程式設計師寫程式時不用去關心記憶體動態分配和垃圾回收的問題,這一切工作都由JVM來處理。雖然我們不需要去處理這些工作,但我們還是有必要了解下java垃圾回收機制的基本原理,畢竟在某些情況是需要我們根據垃圾回收的機制來保證程式的健壯性的(防止記憶體洩漏).

首先我們要明白兩個問題:

  1. 在Java中,什麼物件會被定義為”垃圾”?
  2. 在執行垃圾回收過程中,虛擬機器採用了什麼回收演算法來執行垃圾回收的?

1.什麼物件會被定義為”垃圾”?

在java中是通過引用來和物件進行關聯的,也就是說如果要操作物件,必須通過引用來進行。那麼就可以通過一個簡單的方法引用計數來判斷一個物件是否被回收,假如一個物件沒有任何的一個引用與之關聯,則該物件基本不大可能在其他地方被引用到,那個這個物件就可能成為被回收的物件。 該方法實現簡單,且效率高。但是,該方法也存在一定的缺點,無法解決迴圈引用的方法。什麼是迴圈引用?給一段程式碼展示

<span style="color:#000000"><code><span style="color:#000088">public</span> <span style="color:#000088">class</span> App{
    <span style="color:#000088">public</span> <span style="color:#000088">static</span> <span style="color:#000088">void</span> <span style="color:#009900">main</span>(String[] args) {
        Test object1 = <span style="color:#000088">new</span> Test();
        Test object2 = <span style="color:#000088">new</span> Test();

        object1.<span style="color:#000088">object</span> = object2;
        object2.<span style="color:#000088">object</span> = object1;

        object1 = <span style="color:#000088">null</span>;
        object2 = <span style="color:#000088">null</span>;
    }
}

class Test{
    <span style="color:#000088">public</span> Test <span style="color:#000088">object</span> = <span style="color:#000088">null</span>;
}</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

雖然最後兩句將object1和object2置為null,但是他們由於互相引用,結果導致它們的計數都不為0,那些垃圾收集器就無法回收它們.

所以為了解決這個問題,java中採取了可達性分析法。該方法的基本思想是通過一系列的“GC Roots”物件作為起點進行搜尋,如果在“GC Roots”和一個物件之間沒有可達路徑,則稱該物件是不可達的,不過要注意的是被判定為不可達的物件不一定就會成為可回收物件。被判定為不可達的物件要成為可回收物件必須至少經歷兩次標記過程,如果在這兩次標記過程中仍然沒有逃脫成為可回收物件的可能性,則基本上就真的成為可回收物件了。

這種方法相比引用計數方就更加嚴謹了,並且可能解決迴圈引用的問題。

2.java虛擬機器採取了什麼演算法來執行垃圾回收?

在回答這個問題之前,我們先了解下目前垃圾回收有哪幾種主流的回收演算法.1).Mark-Sweep(標記-清除)演算法 這是最基礎的演算法,該演算法就是標記出需要被回收的物件,等到需要執行GC操作時將標記的物件一併清除,實現垃圾回收。改方法簡單,效率高,但是有個缺點就是會導致記憶體碎片。

2).Copying(複製)演算法 Copying演算法是將記憶體區域劃分為兩塊相同大小的子區域,並且在其中的一塊中執行物件分配,等到這一塊的記憶體用完了,就將該區域還存活著的物件複製到另外一塊記憶體區域上面,然後再把已使用的記憶體空間一次清理掉,這樣就不會導致記憶體碎片的問題,但是有個明顯的缺點,每次只能使用到一半的記憶體,對記憶體壓力大。

3).Mark-Compact(標記-整理)演算法 Mark-Compact演算法是在Mark-Sweep演算法的基礎上進行了改進,演算法標記跟Mark-Sweep一樣,只是在標記完之後,將標記的物件向一端移動,然後清理掉邊界以外的記憶體區域,這樣就解決了記憶體碎片化的問題

3).Generational Collection(分代收集)演算法 這是目前Jvm使用的垃圾回收演算法。它的核心思想是根據物件存活的生命週期將記憶體劃分為若干個不同的區域。分為老年代(Tenured Generation)和新生代(Young Generation)。老年代的記憶體區域的物件一般回收頻率比較低,採用了Mark-Compact演算法,而新生代的記憶體區域由於每次需要回收大量物件,回收頻率較高,所以將該區域又劃分成了一個較大的Eden空間和兩個較小的Suivivor空間,每次使用Eden空間和一個Survivor空間的,當需要回收垃圾時,將Eden空間和該Survivor空間的存活物件複製到另外一塊Survivor空間上,然後清理到Eden和剛才使用的Survivor空間,實現垃圾回收機制.

所以java垃圾回收機制主要關注的重點是可達性分析法還有分代收集演算法,並且瞭解它們的優點。