分代的垃圾回收策略,是基於這樣一個事實:不一樣的對象的生命週期是不同的。所以,不一樣生命週期的對象能夠採起不一樣的收集方式,以便提升回收效率。java
在Java程序運行的過程當中,會產生大量的對象,其中有些對象是與業務信息相關,好比Http請求中的Session對象、線程、Socket鏈接,這類對象跟業務直接掛鉤,所以生命週期比較長。可是還有一些對象,主要是程序運行過程當中生成的臨時變量,這些對象生命週期會比較短,好比:String對象,因爲其不變類的特性,系統會產生大量的這些對象,有些對象甚至只用一次便可回收。算法
試想,在不進行對象存活時間區分的狀況下,每次垃圾回收都是對整個堆空間進行回收,花費時間相對會長,同時,由於每次回收都須要遍歷全部存活對象,但實際上,對於生命週期長的對象而言,這種遍歷是沒有效果的,由於可能進行了不少次遍歷,可是他們依舊存在。所以,分代垃圾回收採用分治的思想,進行代的劃分,把不一樣生命週期的對象放在不一樣代上,不一樣代上採用最適合它的垃圾回收方式進行回收。jvm
堆內存分爲年輕代(Young Generation)和年老代(Old Generation)。年輕代又分爲兩種,一種是Eden區域,另一種是兩個大小對等的Survivor區域。spa
持久代即非堆內存,主要用於存儲一些類的元數據,常量池,java類,靜態文件等信息。持久代對垃圾回收沒有顯著影響,可是有些應用可能動態生成或者調用一些class,例如Hibernate等,在這種時候須要設置一個比較大的持久代空間來存放這些運行過程當中新增的類。持久代大小經過-XX:MaxPermSize=<N>進行設置。.net
當新對象生成,而且在Eden申請空間失敗時,就會觸發Scavenge GC,對Eden區域進行GC,清除非存活對象,而且把尚且存活的對象移動到Survivor區,而後整理Survivor的兩個區。這種方式的GC是對年輕代的Eden區進行,不會影響到年老代。由於大部分對象都是從Eden區開始的,同時Eden區不會分配的很大,因此Eden區的GC會頻繁進行。於是,通常在這裏須要使用速度快、效率高的算法,使Eden區能儘快空閒出來。線程
首先,新對象的內存分配都是先在Eden區域中進行的,當Eden區域的空間不足於分配新對象時,就會觸發年輕代上的垃圾回收,咱們稱之爲"minor garbage collection".同時,每一個對象都有一個「年齡」,這個年齡實際上指的就是該對象經歷過的minor gc的次數。如圖1所示,當對象剛分配到Eden區域時,對象的年齡爲「0」,當minor gc被觸發後,全部存活的對象(仍然可達對象)會被拷貝到其中一個Survivor區域,同時年齡增加爲「1」。並清除整個Eden內存區域中的非可達對象。3d
當第二次minor gc被觸發時(如圖2所示),JVM會經過Mark算法找出全部在Eden內存區域和Survivor1內存區域存活的對象,並將他們拷貝到新的Survivor2內存區域(這也就是爲何須要兩個大小同樣的Survivor區域的緣由),同時對象的年齡加1. 最後,清除全部在Eden內存區域和Survivor1內存區域的非可達對象。對象
當對象的年齡足夠大(這個年齡能夠經過JVM參數進行指定,這裏假定是2),當minor gc再次發生時,它會從Survivor內存區域中升級到年老代中,如圖3所示。blog
當minor gc發生時,又有對象從Survivor區域升級到Tenured區域,可是Tenured區域已經沒有空間容納新的對象了,那麼這個時候就會觸發年老代上的垃圾回收,咱們稱之爲"major garbage collection"。而在年老代上選擇的垃圾回收算法則取決於JVM上採用的是什麼垃圾回收器,經過的垃圾回收器有兩種:Parallel Scavenge(PS) 和Concurrent Mark Sweep(CMS)。生命週期
參考資料
http://www.jianshu.com/p/778dd3848196
http://itindex.net/detail/45308-jvm-%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6-%E7%AD%96%E7%95%A5