java和C#中的內存的分配和釋放都是由虛擬機自動管理的,此前我已經介紹了CLR中GC的對象回收方式,是基於代的內存回收策略,其實在java中,JVM的對象回收策略也是基於分代的思想。這樣做的目的就是為了提高垃圾
回收的性能,避免對堆中的所有對象進行檢查時所帶來的程序的響應的延遲,因為jvm執行GC時,會stop the word,即終止其它線程的運行,等回收完畢,才恢復其它線程的操作。基於分代的思想是:jvm在每一次執行垃圾收集器時,只是對一小部分內存
對象引用進行檢查,這一小部分對象的生命週期也更短,從而加快了垃圾收集的性能。下面我們將來介紹java中的基於代的內存回收算法的基本策略:
一、jvm堆內存的分代劃分
在基於分代的內存回收策略中,堆空間通常都被劃分為3個代,年輕代,年老代(或者tenured代),永久代。在年輕代中又被劃分了三個小的區域,分別為:Eden(伊甸)區,S0區(survivor 0),S1區(survivor 1),如下圖所示:
其中,新的對象總被分配到年經代中,當年輕代空間被填滿時,這時需要執行一次垃圾回收,即執行minor GC,回收不再被引用的對象,並同時提升倖存的對像其年齡,年經代中的倖存對像都有年齡標識字段,一旦其達到一定的閾值,則仍然倖存的對象將被提升到老年代空間中。
老年代的空間用於存放長時間倖存的對象,即生命週期較長的對象,一旦年輕代空間的倖存對象達到一定的年齡閾值後,將被自動提升到年老代,當年老代空間被對象填滿時,這時執行一次Major GC。相較於minor GC, Major GC的執行次數要比minor GC要少很多,同時,Major Gc 執行的時間較Minor Gc要長。因為其涉及到更多的對象掃描。這種分代的思想,也是基於在實踐中,對於新分配的對象具有更短的生命週期,年老的對象具有更長的生命週期所作出的較佳的選擇。
與此同時,Minor Gc 和Major Gc 在執行垃圾收集時,採取的是stop the world event ,即終止正在運行的線程,等GC執行完畢在恢復所有的線程。
對於永久代的內存,主要是用來存放元數據的相關信息,類及其方法的信息。當一個類不再使用時將會被回收,當執行Full GC時,將會掃描永久代內存,對其進行垃圾回收。
二、基於分代的垃圾回收的處理過程
首先,初始時,新對像被分配到Eden區域,s0,s1為空。當Eden中的空間被填滿時,執行一次Minor GC。垃圾收集器會將被引用的對象移動s0區,不再被引用的對象將被刪除,與此同時,對於倖存的對象標識其年齡為1. GC後,Eden和S1區為空如下圖所示。
下一次執行Minor GC後,與先前的執行步驟相同,唯一的區別時,這次的被引用的對象,即倖存下來的對象將會被移動到S1區,與此同時在s0區倖存的對象的年齡會增加1,變成2,如下圖所示。
當再次,執行Minor GC後,與先前的步驟相同,倖存對象會被移到S0區,給倖存對象年齡加1.如下圖所示
最後執行Minor GC 時,發現S1中的倖存的對象年齡達到8(假設閾值設為8),此時該對象將被提升到老年代內存中,如下圖所示。
Z
當老年代堆空間被對象填滿時,將會執行一次Major Gc,將會清除老年代不再被引用的對象,與此同時,對該空間執行壓縮。如下圖所示。
以上這篇淺談jvm中的垃圾回收策略就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持武林網。