1. 程式人生 > 其它 >fullgc觸發條件_記一次生產頻繁出現 Full GC 的 GC日誌圖文詳解

fullgc觸發條件_記一次生產頻繁出現 Full GC 的 GC日誌圖文詳解

場景描述
相信大家都瞭解 jps、jmap、jstack 等常用 java 堆疊輸出命令,有過 dump、gc 分析的經驗,面試中會經常被問到有關 JVM 問題,比如你是否瞭解你的程式在生產環境的基礎配置,堆記憶體、棧記憶體怎麼設定的,又是怎麼估算的大小,或是垃圾回收器及回收垃圾演算法的最佳使用策略。作為專案的核心開發人員,別把這些事當成是架構師要乾的活,因為程式碼可是你一行一行碼出來的,沒人比你更清楚,你得負責從程式開發、黑白盒測試、專案驗收、部署上線、整合交付、運維監控、使用者體驗等環節。越大的企業,專案模組分配的越細,這也並不代表你不需要了解整體系統的效能,其中任何一個環節出問題,都可能導致系統無法正常執行。


藉由這次生產系統頻繁宕機,我們總結一下 JVM 記憶體模型劃分、JVM 啟動堆記憶體相關引數配置及說明、各年齡代的垃圾回收器及回收過程、生產 GC 日誌解讀與分析、系統執行記憶體預估方法、啟動引數如何優化等。希望通過這篇小記來和大家一起交流、一起學習。
正文
2.1 生產 GC日誌檔案
部分截圖如下:

2.2 先看一下 jdk 1.8 的記憶體劃分情況
按年齡劃分為年輕代、老年代、元空間、本地方法區、虛擬機器棧和程式計數器。下圖詳細說明了這幾個記憶體分割槽的關係、JVM 引數說明、儲存的相關內容及各記憶體分割槽的垃圾回收器及垃圾回收演算法。

2.3 生產基礎環境
說明如下:
JDK版本:jdk_1.8


Web容器:Tomcat
題外話:估計市面上都是玩微服務了吧,jdk 版本至少也得 1.8 以上,jdk 1.6 不支援 G1 這麼好用的垃圾收集器,也不支援 lambda 表示式,以及其他好用的特性
2.4 生產 JVM 堆記憶體相關引數
設定如下:

// 初始堆大小-Xms4096M// 最大堆大小-Xmx4096M// 持久代最大值-XX:MaxPermSize=1024M//......

題外話:這份配置一看就有點問題,為什麼到現在才發現,因為系統之前很少出現問題,之前也未設定GC日誌記錄引數,也未曾關心 JVM 引數設定,大家只是在原有的工程進行開發和維護。其中 -Xmn 年輕代未配置(-XX:NewRatio 年輕代與年老代所佔比值也未配置),-XX:PermSize 持久代初始值未配置(存在動態擴容帶來的效能消耗)等


2.5 擷取生產一條 GC 日誌
圖解分析如下:

2019-11-20T17:15:38.906+0800: 672725.775: [GC 2019-11-20T17:15:38.907+0800: 672725.776: [ParNew: 143735K->15199K(153344K), 0.0485240 secs] 2568043K->2439507K(4177280K), 0.0497750 secs] [Times: user=0.20 sys=0.00, real=0.05 secs] 

從以上 GC 日誌檔案結構圖解可以清晰看出,線上生產環境的年輕代總記憶體大小分配約 150M,堆總記憶體大小約 4G,明顯年輕代記憶體分配過小。每次 ParNew GC 老年代變化可以由堆記憶體大小變化和年輕代記憶體大小變化推算。
從下圖 GC 日誌可以看出,線上系統出現頻繁 ParNew GC(即年輕代的 Minor GC),平均大約每 5 分鐘進行一次 Minor GC,即一天平均執行 288 次之多,太可怕了吧!!!唉

郭慕榮部落格園