YGC前後新生代變大?

2021-09-02 00:23:47 字數 1488 閱讀 6274

我們都知道gc是為了釋放記憶體,但是你是否碰到過ygc前後新生代反增不減的情況呢?gc日誌效果類似下面的:

2016-05-18t15:06:13.011+0800: [gc [parnew (promotion failed): 636088k->690555k(707840k), 0.2958900 secs][cms: 1019739k->1019733k(1310720k), 2.6208600 secs] 1655820k->1655820k(2018560k), [cms perm : 205486k->205486k(262144k)], 2.9174390 secs] [times: user=3.74 sys=0.01, real=2.91 secs]
從上面的gc日誌來看,我們新生代使用的是parnew,而老生代用的是cms gc,我們注意到parnew的效果是新生代從636088k新增到了690555k,這是什麼情況?

要解釋這個問題,我們先要弄清楚ygc的過程,parnew是新生代的gc演算法,簡單來說從gc roots開始掃瞄物件,當掃到乙個只要是屬於新生代的物件就將其挪到to space,但是老的物件還不會做釋放,直到gc完成之後再看是否釋放老的物件(比如說上面我們看到了promotion failed的關鍵字,意味著晉公升失敗了,也就是說to和old都裝不下新生代晉公升來的物件,那麼在這種情況下其實是不會對eden和from裡的老物件做釋放的,儘管to space裡已經可能存在乙份副本了),但是在gc前後不管是否晉公升成功,都會對from space和to space做乙個對換,也就是原來的from變成to,原來的to變成from,再來看看列印gc前後記憶體變化的**

void gencollectedheap::print_heap_change(size_t prev_used) const  else 

}size_t gencollectedheap::used() const

return res;

}size_t defnewgeneration::used() const

從上面**我們知道,gc之後的記憶體情況是used()方法返回的,其中新生代的used方法返回的是eden+from的記憶體,同樣的上面的prev_used也是這麼計算的,只是發生在gc之前,這樣一來,根據我上面提到的情況,在gc之後不管是否成功都會做一次from和to的swap,那麼gc之前新生代的使用大小,其實是gc之前eden+from的使用大小,而gc之後的新生代的使用大小,其實是eden+原來的to現在使用的大小,原來的to現在使用的大小其實就是在gc過程中將eden和from拷貝過來的物件所佔的大小。

綜上分析你應該知道為什麼會出現這種情況了,其實是一種特殊情況,只有在出現promotion failed的情況下才會發生這樣的情況,因為在這個情況下存在to裡新增物件,而from和eden不會變化的情況。

新生代的配置

引數 xmn可以用於設定新生代的大小。設定乙個較大的新生代大小會減少老年代的大小,此引數對系統效能以及gc影響很大。新生代的大小一般設定為整個堆空間的1 3到1 4左右。引數 xx survivorratio用來設定新生代中eden空間和from to空間的比例關係,如下 xx survivorra...

Young Gen新生代演算法

sun oracle 的 hotspot jvm 又把新生代進一步劃分為 3 個區域 1.乙個相對大點的區域,稱為 伊甸園區 eden 2.兩個相對小點的區域稱為 from 倖存區 survivor 和 to 倖存區 survivor 按照規定,新物件會首先分配在 eden 中 如果新物件過大,會直...

關於新生代和老年代

目錄前言 一 年輕代 1.1survivor區解釋 二 老年代 三 full gc 總結 感謝 這裡主要記錄一點對於新生代和老年代的整理了解 也叫新生代,顧名思義,主要是用來存放新生的物件。新生代又細分為eden區 survivorfrom區 survivorto區。如果新生物件在eden區無法分配...