淺談JVM垃圾回收機制

sunspot堆內存分爲三個區域:

· 新生代(Young)

新生代包括兩個區:Eden區和Survivor區,其中Survivor區一般也分成兩塊,簡稱Survivor1 Space 和 Survivor2 Space (或者From Space 和 To Space)。新生代通常存活時間較短,因此基於標記清除複製算法來進行回收,掃描出存活的對象,並複製到一塊新的完全未使用的空間中,對應於新生代,就是在Eden和From或To之間copy。新生代採用空閒指針的方式來控制GC觸發,指針保持最後一個分配的對象在新生代區間的位置,當有新的對象要分配內存時,用於檢查空間是否足夠,不夠就觸發GC。當連續分配對象時,對象會逐漸從eden到Survior,最後到舊生代。

可以採用串行處理和並行處理器

· 老年代(Old)

在垃圾回收多次,如果對象仍然存活,並且新生代的空間不夠,則對象會存放在老年代。

在老年代採用的是 標記清除壓縮算法。因爲老年代的對象一般存活時間比較長,每次標記清除之後,會有很多的零碎空間,這個就是所謂的浮動垃圾。當老年代的零碎空間不足以分配一個大的對象的時候,就會採用壓縮算法。在壓縮的時候,應用需要暫停。

可以採用串行處理,並行處理器,以及併發處理器。

· 持久代(Permanent)

這部分空間主要存放java方法區的數據以及啓動類加載器加載的對象。這一部分對象通常不會被回收。所以持久代空間在默認的情況下是不會被垃圾回收的。


首先的問題是:jvm如何知道那些對象需要回收 ?

目前有兩種算法

· 引用計數法

每個對象上都有一個引用計數,對象每被引用一次,引用計數器就+1,對象引用被釋放,引用計數器-1,直到對象的引用計數爲0,對象就標識可以回收

這個可以用數據算法中的圖形表示,對象A-對象B-對象C 都有引用,所以不會被回收,對象B由於沒有被引用,沒有路徑可以達到對象B,對象B的引用計數就就是0,對象B就會被回收。

但是這個算法有明顯的缺陷,對於循環引用的情況下,循環引用的對象就不會被回收。

· root搜索算法

這種算法目前定義了幾個root,也就是這幾個對象是jvm虛擬機不會被回收的對象,所以這些對象引用的對象都是在使用中的對象,這些對象未使用的對象就是即將要被回收的對象。簡單就是說:如果對象能夠達到root,就不會被回收,如果對象不能夠達到root,就會被回收。


基本上 jvm內存回收有三種 基本算法

1、標記-清除

標記清除的算法最簡單,主要是標記出來需要回收的對象,然後然後把這些對象在內存的信息清除。

2、標記-清除-壓縮

這個算法是在標記-清除的算法之上進行一下壓縮空間,重新移動對象的過程。因爲標記清除算法會導致很多的留下來的內存空間碎片,隨着碎片的增多,嚴重影響內存讀寫的性能,所以在標記-清除之後,會對內存的碎片進行整理。最簡單的整理就是把對象壓縮到一邊,留出另一邊的空間。由於壓縮空間需要一定的時間,會影響垃圾收集的時間。

3、 標記-清除-複製

這個算法是吧內存分配爲兩個空間,一個空間(A)用來負責裝載正常的對象信息,,另外一個內存空間(B)是垃圾回收用的。每次把空間A中存活的對象全部複製到空間B裏面,在一次性的把空間A刪除。這個算法在效率上比標記-清除-壓縮高,但是需要兩塊空間,對內存要求比較大,內存的利用率比較低。適用於短生存期的對象,持續複製長生存期的對象則導致效率降低








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