JVM學習(二) 堆內存 垃圾回收(GC)策略

堆內存概述:堆是 JVM 所管理的最大的一塊內存空間,主要用於存放各種類的實例對象。

堆的垃圾回收策略:堆是垃圾回收器管理的主要區域,99%的垃圾回收發生在 堆,另外1%發生在方法區,因此又稱之爲”GC堆”。JVM對於堆的垃圾回收,採用分代收集的策略。

堆的兩個區域:根據堆中對象的存活週期將堆內存分爲 新生代 ( Young )、老年代 ( Old )。

堆內存分代的原因:分代是爲了優化 GC 性能。如果沒分代 GC 需要對 堆內存 所有區域進行掃描。分代後, CG將指定區域(新聲代:存儲大量朝生夕死的對象)進行回收。這樣就可以騰出很大的空間

一、新生代

新生代( Young ):很快就會被GC回收掉的或者不是特別大的對象。

新生代 ( Young )區域:Eden(伊甸<dian>園)和兩個Survivor(倖存者,分別叫做 Form 和 To)。新創建的對象都分配至 Eden 區中,當經過 GC 後任存活,將其移至 Survivor區中。每當一次 GC過後,存活在 Survivor 區中的對象就會 加一歲 ,當到一定的程度時,就移至 老生代

新生代 GC算法:使用的是複製算法,複製算法的基本思想就是將內存分爲兩塊,每次只用其中一塊,當這一塊內存用完,就將還活着的對象複製到另外一塊上面。這樣的話就不會產生內存碎片。

新生代 GC算法 邏輯:在GC開始的時候,對象只會存在於Eden區和名爲“From”的Survivor區,Survivor區“To”是空的。緊接着進行GC,Eden區中所有存活的對象都會被複制到“To”,而在“From”區中,仍存活的對象會根據他們的年齡值來決定去向。年齡達到一定值(年齡閾值,可以通過-XX:MaxTenuringThreshold來設置)的對象會被移動到年老代中,沒有達到閾值的對象會被複制到“To”區域。經過這次GC後,Eden區和From區已經被清空。這個時候,“From”和“To”會交換他們的角色,也就是新的“To”就是上次GC前的“From”,新的“From”就是上次GC前的“To”。不管怎樣,都會保證名爲To的Survivor區域是空的。Minor GC會一直重複這樣的過程,直到“To”區被填滿,“To”區被填滿之後,會將所有對象移動到年老代中。

特點: 
a) 新創建的對象都存放在這個區域
b) 此區域較小,GC 頻率較高
c) 因算法與對象存儲特點,該區域GC效率非常高

二、老生代

老生代( Old) GC算法:複製算法在對象存活率較高的老年代會進行很多次的複製操作,效率很低,所以老年代不適用複製算法。針對老年代對象存活率高的特點,提出了一種稱之爲”標記-整理算法”。首先標記出所有需要回收的對象 ,然後將所有存活對象都向一端移動,然後直接清理掉端邊界以外的內存。

特點: 
a) 將在"新生代"中生存了較長時間的對象轉移過來
b) 區域一般要大一些而且增長的速度相對於"新生代"要慢一些
c) 垃圾回收的執行頻率也會低很多

三、相關參數

1)-XX:NewSize和-XX:MaxNewSize:用於設置年輕代的大小,建議設爲整個堆大小的1/3或者1/4,兩個值設爲一樣大。

2)-XX:SurvivorRatio:用於設置Eden和其中一個Survivor的比值,這個值也比較重要。

3)-XX:+PrintTenuringDistribution:這個參數用於顯示每次 GC時Survivor區中各個年齡段的對象的大小。

4).-XX:InitialTenuringThreshol和-XX:MaxTenuringThreshold:用於設置晉升到老年代的對象年齡的最小值和最大值,每個對象在堅持過一次GC之後,年齡就加1。

 

在此附上一位阿里大佬的 老生代增長過快的原因排查

https://www.aliyun.com/jiaocheng/769902.html

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