何時會發生FullGC

堆內存劃分爲 Eden、Survivor 和 Tenured/Old 空間,以下圖所示:java

從年輕代空間(包括 Eden 和 Survivor 區域)回收內存被稱爲 Minor GC,對老年代GC稱爲Major GC,而Full GC是對整個堆來講的,在最近幾個版本的JDK裏默認包括了對永生代即方法區的回收(JDK8中無永生帶了),出現Full GC的時候常常伴隨至少一次的Minor GC,但非絕對的。Major GC的速度通常會比Minor GC慢10倍以上。下邊看看有那種狀況觸發JVM進行Full GC及應對策略。數組

1. System.gc()方法的調用

此方法的調用是建議JVM進行Full GC,雖然只是建議而非必定,但不少狀況下它會觸發 Full GC,從而增長Full GC的頻率,也即增長了間歇性停頓的次數。強烈影響系建議能不使用此方法就別使用,讓虛擬機本身去管理它的內存,可經過經過-XX:+ DisableExplicitGC來禁止RMI調用System.gc。安全

二、老年代空間不足

老年代空間只有在新生代對象轉入及建立大對象、大數組時纔會出現不足的現象,當執行Full GC後空間仍然不足,則拋出以下錯誤:
java.lang.OutOfMemoryError: Java heap space 
爲避免以上兩種情況引發的Full GC,調優時應儘可能作到讓對象在Minor GC階段被回收、讓對象在新生代多存活一段時間及不要建立過大的對象及數組。併發

三、永生區空間不足

JVM規範中運行時數據區域中的方法區,在HotSpot虛擬機中又被習慣稱爲永生代或者永生區,Permanet Generation中存放的爲一些class的信息、常量、靜態變量等數據,當系統中要加載的類、反射的類和調用的方法較多時,Permanet Generation可能會被佔滿,在未配置爲採用CMS GC的狀況下也會執行Full GC。若是通過Full GC仍然回收不了,那麼JVM會拋出以下錯誤信息:
java.lang.OutOfMemoryError: PermGen space 
爲避免Perm Gen佔滿形成Full GC現象,可採用的方法爲增大Perm Gen空間或轉爲使用CMS GC。spa

四、CMS GC時出現promotion failed和concurrent mode failure

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

具體緣由和解決方案能夠查看使用CMS垃圾收集器產生的問題和解決方案設計

五、HandlePromotionFailure

在發生Minor GC以前,虛擬機會先檢查老年代最大可用的連續空間是否大於新生代全部對象總空間,若是這個條件成立,那麼Minor GC能夠確保是安全的。若是不成立,則虛擬機會查看HandlePromotionFailure設置值是否容許擔保失敗。若是容許,那麼會繼續檢查老年代最大可用的連續空間是否大於歷次晉升到老年代對象的平均大小,若是大於,將嘗試着進行一次Minor GC,儘管此次Minor GC是有風險的;若是小於,或者HandlePromotionFailure設置不容許冒險,那這時也要改成進行一次Full GC。日誌

統計獲得的Minor GC晉升到老年代的平均大小大於老年代的剩餘空間,這是一個較爲複雜的觸發狀況,例如程序第一次觸發Minor GC後,有6MB的對象晉升到老年代,那麼當下一次Minor GC發生時,首先檢查老年代的剩餘空間是否大於6MB,若是小於6MB,則執行Full GC。
當新生代採用PS GC時,方式稍有不一樣,PS GC是在Minor GC後也會檢查,例如上面的例子中第一次Minor GC後,PS GC會檢查此時舊生代的剩餘空間是否大於6MB,如小於,則觸發對舊生代的回收。
除了以上4種情況外,對於使用RMI來進行RPC或管理的Sun JDK應用而言,默認狀況下會一小時執行一次Full GC。可經過在啓動時經過  java -Dsun.rmi.dgc.client.gcInterval=3600000來設置Full GC執行的間隔時間或經過-XX:+ DisableExplicitGC來禁止RMI調用System.gc。對象

六、堆中分配很大的對象

所謂大對象,是指須要大量連續內存空間的java對象,例如很長的數組,此種對象會直接進入老年代,而老年代雖然有很大的剩餘空間,可是沒法找到足夠大的連續空間來分配給當前對象,此種狀況就會觸發JVM進行Full GC。blog

爲了解決這個問題,CMS垃圾收集器提供了一個可配置的參數,即-XX:+UseCMSCompactAtFullCollection開關參數,用於在「享受」完Full GC服務以後額外免費贈送一個碎片整理的過程,內存整理的過程沒法併發的,空間碎片問題沒有了,但提頓時間不得不變長了,JVM設計者們還提供了另一個參數 -XX:CMSFullGCsBeforeCompaction,這個參數用於設置在執行多少次不壓縮的Full GC後,跟着來一次帶壓縮的。

相關文章
相關標籤/搜索