1. 程式人生 > >觸發Full GC執行的情況

觸發Full GC執行的情況

觸發FULL GC的四種情況

1. System.gc()方法呼叫

一般情況下禁止使用此方法,讓JVM自己決定FULL GC即可。

2. 老生代空間不足

老生代空間只有在新生代物件轉入及建立為大物件、大陣列時才會出現不足的現象,會出現FULL GC情況。

當執行Full GC後空間仍然不足,則丟擲如下錯誤:

java.lang.OutOfMemoryError: Java heap space 

為避免以上兩種狀況引起的FullGC,調優時應儘量做到讓物件在新生代Minor GC階段被回收、讓物件在新生代多存活一段時間及不要建立過大的物件及陣列。

3. Permanet Generation
永久代空間滿

PermanetGeneration永久代(方法區)中存放的為一些class的資訊等,當系統中要載入的類、反射的類和呼叫的方法較多時,Permanet Generation可能會被佔滿,在未配置為採用CMS GC的情況下會執行Full GC。如果經過Full GC仍然回收不了,那麼JVM會丟擲如下錯誤資訊:

java.lang.OutOfMemoryError: PermGen space 

為避免Perm Gen佔滿造成Full GC現象,可採用的方法為增大Perm Gen空間或轉為使用CMS GC。

4. CMS GC時出現promotion failedconcurrent mode failure

對於採用CMS進行老生代GC的程式而言,尤其要注意GC日誌中是否有promotion failed和concurrent mode failure兩種狀況,當這兩種狀況出現時可能會觸發Full GC。

promotionfailed是在進行Minor GC時,survivor space放不下、物件只能放入老生代,而此時老生代也放不下造成的;

concurrent mode failure是在執行CMS GC的過程中同時有物件要放入老生代,而此時生代空間不足造成的。

應對措施為:增大survivorspace、老生代空間或調低觸發併發GC的比率,但在JDK 5.0+、6.0+的版本中有可能會由於JDK的bug29導致CMS在remark完畢後很久才觸發sweeping動作。對於這種狀況,可通過設定-XX:CMSMaxAbortablePrecleanTime=5(單位為ms)來避免。

4. 統計得到的Minor GC晉升到老生代的平均大小大於老生代的剩餘空間

這是一個較為複雜的觸發情況,Hotspot為了避免由於新生代物件晉升到老生代導致舊生代空間不足的現象,在進行Minor GC時,做了一個判斷,如果之前統計所得到的Minor GC晉升到老生代的平均大小大於老生代的剩餘空間,那麼就直接觸發Full GC。

例如程式第一次觸發MinorGC後,有6MB的物件晉升到舊生代,那麼當下一次Minor GC發生時,首先檢查老生代的剩餘空間是否大於6MB,如果小於6MB,則執行Full GC。

儘量避免FULLGC的方法

1. 增大old老年代記憶體空間

2. 儘可能減少young年輕代到老年代。調整晉升年齡-XX:PretenureSizeThreshold Survrvor的大小。

3. 優化系統性能