最近接到運營部門的反饋網站時常會出現小批量的502
且在網站出現502
以前反應特別慢,刷新幾回之後又能夠正常訪問了。正則表達式
項目部署了兩臺機器,其中一臺出現重啓的狀況,部分用戶在訪問當前服務器時正好機器重啓了,致使訪問異常。數組
查看生產環境日誌發現其中一臺機器重啓了屢次,從warpper log
中能夠發現warpper
在屢次ping
不通時自動重啓了屢次,從運維那邊確認這臺服務器屢次出現無響應的狀況。此時第一時間想到OOM
進一步查看日誌並無發現OutOfMemoryException
拋出,也沒有StackOverflowException
。bash
經過top
命令查看生產環境CPU
佔用一直很是高,load
也一直高居不下,GC長時間佔用CPU
資源。服務器
進一步查看GC
狀況,發如今重啓後很短的時間內FGC
次數達7W+;Old Generation
持續佔用100%,而每次FGC
的時間又很是的短.運維
jstat -gcUtil [pid] 1000
jvm
在經過jmap -histo [pid]
查看內存實例狀況也沒有發現異常。工具
FGC
?。
因爲沒有觸發OOM
手動添加如下啓動參數,打印FGC
先後堆內存狀況優化
-XX:+HeapDumpBeforeFullGC
-XX:+HeapDumpAfterFullGC
-XX:HeapDumpPath=/tmp
複製代碼
果真,重啓後短期內開始輸出 dump網站
接下來使用jvisualvm
(JDK 自帶的內存分析工具) 查看堆dump
文件。 如下列出FGC
先後的堆dump
類視圖spa
對比FGC
先後發如今FGC
以前存在大量的int[]
和char[]
數組,且數組的length
都很是大,而這些大數組在FGC
以後又被有效的回收了。對jvm
垃圾回收有了解的同窗應該知道,jvm
爲了不頻繁的移動大對象會將大對象直接建立在Old Generation
。此時開始懷疑是否是Old Generation
的空間不夠了,逐一排查線上環境的jvm
啓動參數。
-Xms 2048
-Xmx 2048
...
-Xmn 2000
-
複製代碼
......
最後發現,因爲這臺機器內存只有2G
而新生代分配的內存卻達到了2000M
剩下的內存只有48M
。而大數組又會直接分配到Old Generation
當Old Generation
沒有足夠的空間來存放大數組對象時,就可能觸發FGC
修改 -Xmn 683
默認新生代和老年代的比值爲1:2
。從新發布問題解決,top
、jstat -gc
查看服務器狀態各項數據都很是可愛。
因爲項目已經跑了好幾年,一開始的思路都在查找項目代碼層面的問題,絲毫沒有意Jvm
啓動參數的問題,其實對一些有經驗的同窗來講發現問題蒐集到的一些信息就能夠定位問題。如:
GC
那張圖就能夠明顯的看出問題。FGC
異常頻繁(7W+),但FGCT
卻不高(1.9W),這說明每次 FGC
的效率很是高。而每次FGC
的時候New Generation
的佔用卻很是少,能夠排除是由於程序問題短期內產生大量新對象觸發的 FGC
,這些都提供了直接的排查方向應該從:致使FGC
觸發的條件入手,而不是找程序的問題。FGC
以前沒有有效的觸發YGC
。還有一點值得注意,jvm
啓動參數的默認值在絕大多數狀況下均可以完美的運行,不到系統優化的最後一步儘可能使用默認配置,最後還有一點疑問大量的int[]
、char[]
數組是從那裏來得?經過分析項目中的代碼,以及FGC
前存在大量的pattern
(正則表達式)相關對象分析,初步懷疑是由於項目中大量不規範的使用Pattern
致使的。
OutOfMemoryException
、StackOverflowException
拋出。GC
狀況。GC
先後的dump
文件。