JVM1小時1次FGC調優
阿新 • • 發佈:2019-02-04
通過cat發現專案一個奇怪現象,每隔一個小時都會進行一次fgc,很有規律,且和專案使用高低峰無關。最開始以為是記憶體洩漏。通過觀察,發現線下研發環境也一樣,fgc時堆的年輕代,年老代,持久代的記憶體都未佔滿,應該不是記憶體洩漏問題。開始懷疑專案中使用了JMX監控zookeeper狀態時,保留了JMXConnector的連線物件。研發環境把這塊去掉,觀察發現沒有fgc問題。問題找到了,上網搜了下,果然有前輩遇到過有現成的解決方案:
引發的原因是由於使用了RMI,會自動1小時呼叫1次system.gc()。
大多數的應用雖然配置了CMS gc方式,但是如果沒有使用-XX:+ExplicitGCInvokesConcurrent,則會出現顯示呼叫system.gc(),且不會進行 CMS的FGC,帶來的影響是造成tps的波動(fgc停機時間越長,則波動會越大)。 收集各方的意見後,總結針對此類問題的解決方法如下: 1、增加引數 -XX:+DisableExplicitGC-XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses -Dsun.rmi.dgc.client.gcInterval=36000000 -Dsun.rmi.dgc.server.gcInterval=36000000
考慮使用ExplicitGCInvokesConcurrentAndUnloadsClasses而不是ExplicitGCInvokesConcurrent,擔心有通過反射等方式載入的類之後並未被使用,還有通過maven傳遞依賴過來的jar包太多,有很多也許執行時並未用到,能通過垃圾回收會清理持久代中不再使用的classes。如果之後發現有執行時類找不到的錯誤,則再改回ExplicitGCInvokesConcurrent 。10小時觸發一次(這個時間設定需要觀察堆記憶體的狀態變化)。-Dsun.rmi.dgc.client.gcInterval=36000000這個其實可以不配的,伺服器預設都是配置-server的。
之所以不用1方案,遮蔽System.gc()還是有風險的。