JVM觸發Full GC的條件

Java虛擬機主流的垃圾收集器:cms、G1 。未來的趨勢是基於大內存回收的ZGC,ZGC也是Jdk11版本的默認垃圾收集器。

以jdk1.8爲例,講講觸發Full GC的條件:

è¿éåå¾çæè¿°

圖中展示了7種不同分代的收集器:Serial、ParNew、Parallel Scavenge、Serial Old、Parallel Old、CMS、G1;

新生代收集器:Serial、ParNew、Parallel Scavenge;

老年代收集器:Serial Old、Parallel Old、CMS;

整堆收集器:G1;

觸發Full GC的條件

1、老年代空間不足

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

2、方法區空間不足

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。

3、通過Minor GC後進入老年代的平均大小大於老年代的可用內存

如果發現統計數據說之前Minor GC的平均晉升大小比目前old gen剩餘的空間大,則不會觸發Minor GC而是轉爲觸發full GC

4、由Eden區、From Space區向To Space區複製時,對象大小大於To Space可用內存,則把該對象轉存到老年代,且老年代的可用內存小於該對象大小

5、System.gc()方法的調用

此方法的調用是建議JVM進行Full GC,雖然只是建議而非一定,但很多情況下它會觸發 Full GC,從而增加Full GC的頻率,也即增加了間歇性停頓的次數。強烈影響系建議能不使用此方法就別使用,讓虛擬機自己去管理它的內存,可通過通過-XX:+ DisableExplicitGC來禁止RMI(Java遠程方法調用)調用System.gc。

6、concurrent mode failure

CMS垃圾收集器特有的錯誤,CMS的垃圾清理和引用線程是並行進行的,如果在並行清理的過程中老年代的空間不足以容納應用產生的垃圾,則會拋出“concurrent mode failure”。

concurrent mode failure影響
  老年代的垃圾收集器從CMS退化爲Serial Old,所有應用線程被暫停,停頓時間變長。

可能原因及方案
原因1:CMS觸發太晚
方案:將-XX:CMSInitiatingOccupancyFraction=N調小;

原因2:空間碎片太多
方案:開啓空間碎片整理,並將空間碎片整理週期設置在合理範圍;

-XX:+UseCMSCompactAtFullCollection (空間碎片整理)
-XX:CMSFullGCsBeforeCompaction=n
原因3:垃圾產生速度超過清理速度
晉升閾值過小;
Survivor空間過小,導致溢出;
Eden區過小,導致晉升速率提高;
存在大對象;

 

 

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