GC的三種收集方法

注:轉自 

https://blog.csdn.net/skp127/article/details/51993696

https://blog.csdn.net/zdy0_2004/article/details/43030659

jvm 分代回收詳解http://www.blogjava.net/ldwblog/archive/2013/07/24/401919.html

3中基本的回收算法: 1. 標記-清除法 2. 複製 算法 3.標記-整理法

1,標記-清除法

        將不用的對象實例標記,然後清除 。 缺點 會產生大量內存碎片。

2 ,複製 算法

        把內存分成AB 2塊,每次只是用其中的一塊。當A塊用完後,把A中還存活的對象複製到B中,然後將A塊內存清空。不會產生內存碎片。缺點 內存使用率不高。

3,標記-整理法

        當存活的實例過多時,如果複製的話,效率不高,不合適老生代。 這時,把存活的對象標記出來,全部移動到一端,然後對另外一部分進行清除。

一些高級的GC算法 ,分代回收 、增量回收、並行回收

1. 分代回收

        在分代回收中,對象按照生成的時間進行分代,剛剛生成不久的年輕對象劃爲新生代(Young generation),而存活了較長時間的對象則劃爲老生代(Old generation)。

            在java Jvm中,針對堆內存的新生代 採用複製算法,將新生代分爲按8:1:1 分爲Eden 區 、Survivor From 區、Survivor To 區。其中Survivor Form 區和Survivor To 區沒有區別 ,在該區域的回收一般比較頻繁,稱作:Minor GC;針對老生代,由於該區的對象存活時間比較長,比較穩定,一般採取標記-整理法。在該區域額度回收稱作Major GC 或者 Full GC ,速度較慢,是Minor的10倍。

            按照前面的方式,從老生代對象對新生代的引用怎麼辦呢?如果指掃描新生代區域的話,那麼從老生代對新生代的引用就不會被檢測到。如果一個年輕的對象只有來自老生代的引用,就會被誤認爲已經“死亡”了。因此,在分代回收中,會對對象的更新進行監視,將從老生代對新生代的引用,記錄在一個叫做記錄集(remembered set)的表中。在執行小回收的過程中,這個記錄集也作爲一個根來對象。爲了讓分代回收正確工作,必須使記錄集的內容報紙更新。爲此,在老生代到新生代的引用產生的瞬間,就必須對該引用進行記錄,而負責執行這個操作的子程序,需要被嵌入到所有設計對象更新操作的地方。這個負責記錄引用的子程序是這樣工作的:設有兩個對象A和B,當對A的內容進行改寫並加入對B的引用,如果A屬於老生代對象,並且B屬於新生代對象,則將該引用添加到記錄集中。這種檢查程序需要對所有涉及修改對象內容的地方進行保護,因此被成爲寫屏障(Writes barrier).寫屏障不僅用於分代回收,同時也用在很多其他的GC算法中。

2.增量回收 

        在對實時性要求很高的程序中,比起縮短GC的平均中斷時間,往往更重視縮短GC的最大中斷時間。例如,在機器人的姿勢控制程序中,如果因爲GC而讓控制程序中斷了0.1秒,機器人可能就摔倒了。或者車輛控制程序因爲GC而延遲相應的花,後果也是不堪設想的。在這些對實時性要求很高的程序中,必須能夠對GC所產生的中斷做出預測。例如可以將最多中斷10毫秒作爲附加條件。在一般的GC算法中,GC產生的中斷時間與對象的數量和狀態有關。因此,爲了維持程序的實時性,不等到GC全部完成,而是將GC操作細分成多個部分逐一執行。這種方式被成爲增量回收(Incremental GC)。在增量回收中GC過程是漸進的,再回首過程中程序本身會繼續運行,對象之間的引用關旭也可能發生變化。如果已經完成掃描和標記的對象被修改,對新的對象產生了引用,這個新的對象就不會被標記,明明是存“存活”的對象卻被回收掉了。爲了避免這樣的問題,和分代回收一樣也採用了寫屏障。當已經被標記的對象的引用關係發生變化時,通過寫屏障會將新被引用的對象作爲掃描的起始點記錄下來。由於增量回收的過程是分佈漸進式的,可以將中斷時間控制在一定長隊之內。另一方面由於終端操作需要消耗一定的時間,GC所消耗的總時間就會相應的增加。

3. 並行回收 

            最近的計算機中,一塊芯片上搭載多個CPU核心的多核處理器已經逐漸普及。例如core i7就擁有6核12線程。

在這樣的環境中,就需要通過利用多線程來充分發揮CPU的性能。並行回收正是通過最大限度利用CPU的處理能力來進行GC操作的一種方式。並行回收的基本原理是,在原有的程序運行的同事進行GC操作,這一點和增量回收是相似的。不過,相對於在一個CPU上進行GC任務分割的增量回收來說,並行回收可以利用多CPU的性能,儘可能讓這些GC任務並行進行。由於軟件運行和GC操作是同事進行的,因此就會遇到和增量回收同樣的問題。爲了解決這個問題,並行回收也需要用寫屏障來對當前狀態信息保持更新。不過,讓GC操作完全並行,而一點不影響原有程序運行,是做不到的。因此在GC操作的某些特定階段,還是需要中斷原有程序的運行。

一些名詞解釋

            新生代 GC(Minor GC):指發生在新生代的垃圾收集動作,因爲 Java 對象大多都具備朝生夕滅的特性,所以 Minor GC 非常頻繁,一般回收速度也比較快。

             老年代 GC(Major GC  / Full GC):指發生在老年代的 GC,出現了 Major GC,經常會伴隨至少一次的 Minor GC(但非絕對的,在 ParallelScavenge 收集器的收集策略裏就有直接進行 Major GC 的策略選擇過程) 。MajorGC 的速度一般會比 Minor GC 慢 10倍以上。


            虛擬機給每個對象定義了一個對象年齡(Age)計數器。如果對象在 Eden 出生並經過第一次 Minor GC 後仍然存活,並且能被 Survivor 容納的話,將被移動到 Survivor 空間中,並將對象年齡設爲 1。對象在 Survivor 區中每熬過一次 Minor GC,年齡就增加 1 歲,當它的年齡增加到一定程度(默認爲 15 歲)時,就會被晉升到老年代中。對象晉升老年代的年齡閾值,可以通過參數 -XX:MaxTenuringThreshold 來設置。

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