觸發JVM進行Full GC的情況及應對策略
很多人都分不清 Major GC, Full GC 的概念,事實上我查了下資料,也沒有查到非常精確的Major GC和Full GC的概念定義。分不清這兩個概念可能就會對這個問題疑惑:Full GC會引起Minor GC嗎?
經過一系列的查詢和對JVM表現的分析,基本可以給Full GC 下一個定義了,這篇說一說概念和理由。
堆記憶體劃分為 Eden、Survivor 和 Tenured/Old 空間,如下圖所示:
從年輕代空間(包括 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。
2、老年代代空間不足
老年代空間只有在新生代物件轉入及建立為大物件、大陣列時才會出現不足的現象,當執行Full GC後空間仍然不足,則丟擲如下錯誤:
java.lang.OutOfMemoryError: Java heap space
為避免以上兩種狀況引起的Full GC,調優時應儘量做到讓物件在Minor GC階段被回收、讓物件在新生代多存活一段時間及不要建立過大的物件及陣列。
3、永生區空間不足
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。
4、CMS GC時出現promotion failed和concurrent mode failure
對於採用CMS進行老年代GC的程式而言,尤其要注意GC日誌中是否有promotion failed和concurrent mode failure兩種狀況,當這兩種狀況出現時可能
會觸發Full GC。
promotion failed是在進行Minor GC時,survivor space放不下、物件只能放入老年代,而此時老年代也放不下造成的;concurrent mode failure是在
執行CMS GC的過程中同時有物件要放入老年代,而此時老年代空間不足造成的(有時候“空間不足”是CMS GC時當前的浮動垃圾過多導致暫時性的空間不足觸發Full GC)。
對措施為:增大survivor space、老年代空間或調低觸發併發GC的比率,但在JDK 5.0+、6.0+的版本中有可能會由於JDK的bug29導致CMS在remark完畢
後很久才觸發sweeping動作。對於這種狀況,可通過設定-XX: CMSMaxAbortablePrecleanTime=5(單位為ms)來避免。
5、統計得到的Minor GC晉升到舊生代的平均大小大於老年代的剩餘空間
這是一個較為複雜的觸發情況,Hotspot為了避免由於新生代物件晉升到舊生代導致舊生代空間不足的現象,在進行Minor GC時,做了一個判斷,如果之
前統計所得到的Minor GC晉升到舊生代的平均大小大於舊生代的剩餘空間,那麼就直接觸發Full 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。
6、堆中分配很大的物件
所謂大物件,是指需要大量連續記憶體空間的java物件,例如很長的陣列,此種物件會直接進入老年代,而老年代雖然有很大的剩餘空間,但是無法找到足夠大的連續空間來分配給當前物件,此種情況就會觸發JVM進行Full GC。
為了解決這個問題,CMS垃圾收集器提供了一個可配置的引數,即-XX:+UseCMSCompactAtFullCollection開關引數,用於在“享受”完Full GC服務之後額外免費贈送一個碎片整理的過程,記憶體整理的過程無法併發的,空間碎片問題沒有了,但提頓時間不得不變長了,JVM設計者們還提供了另外一個引數 -XX:CMSFullGCsBeforeCompaction,這個引數用於設定在執行多少次不壓縮的Full GC後,跟著來一次帶壓縮的。
相關文章
- jvm hotspot的minor major full gc之間的關係,以及哪些情況下會觸發full gcJVMHotSpotGC
- 總結Minor GC、Full GC觸發條件GC
- Minor GC、Major GC以及Full GC的介紹及對比GC
- JVM 系列文章之 Full GC 和 Minor GCJVMGC
- jstat命令檢視jvm的GC情況 (以Linux為例)JSJVMGCLinux
- JVM記憶體-GC策略JVM記憶體GC
- JVM垃圾回收——新生代,老年代,永久代,Minor GC,Full GCJVMGC
- 每日一個知識點:什麼時候會觸發Full GCGC
- JVM GC 與 記憶體分配策略JVMGC記憶體
- Full GC (Metadata GC Threshold)GC
- 軟體定義安全的發展及應對策略
- Go語言對Android原生應用開發的支援情況GoAndroid
- 無GPU情況下對cuda程式進行功能性測試GPU
- 如何在開發資源或能力不足的情況下進行敏捷開發?敏捷
- 什麼情況下進行效能測試
- Windows 98 在沒有註冊的情況下對系統進行更新(轉)Windows
- 第一週JVM核心技術-工具與GC策略JVMGC
- Java GC專家系列4:Apache的MaxClients設定及其對Tomcat Full GC的影響JavaGCApacheclientTomcat
- DOM對映的特殊情況
- 從一次 FULL GC 卡頓談對服務的影響GC
- CIO:採用多雲策略的情況分析
- 聊聊東南亞情況和遊戲發行遊戲
- JVM面試問題系列:JVM 配置常用引數和常用 GC 調優策略JVM面試GC
- 我國虛擬現實產業發展情況及推進工作思路產業
- JVM的GC日誌JVMGC
- Eclipse-Eclipse和對應的Jdk版本匹配情況EclipseJDK
- Oracle RAC中驗證LUN_ID對應情況Oracle
- 一次JVM_OLD區佔用過高、頻繁Full GC的解決過程JVMGC
- SELinux on Android的進展情況LinuxAndroid
- 聊一聊 JVM 的 GCJVMGC
- JVM系列之GCJVMGC
- IT職場:哪些情況下需要進行詳細的價值流分析?
- 在JVM執行時開啟GC日誌JVMGC
- JVM調優——JVM監控工具jvisualvm的使用及GC外掛安裝JVMLVMGC
- Java1.7各種GC均會對PermGen進行回收JavaGC
- MongoDB的Motor驅動器進度情況MongoDB
- PHP應避免使用addslashes()的情況PHP
- 檢測手機對MMAPI支援的情況API