記一次由于noclass gc引起的JDK8GC bug

前言

????其實這個問題在我負責的項目里面已經(jīng)出現(xiàn)過一次了,但由于第一次出現(xiàn)并解決的時候我并不負責這個項目,導致印象不是很深,但沒有想到今天在測試環(huán)境又復現(xiàn)了,于是我相當于又重復了一遍之前的排查過程,當然也請教了其他的同事,所以我覺得有必要記錄下來(事不過三,還是沒有記?。菜闶且淮蜧C問題排查的經(jīng)驗了。

問題發(fā)生

? ? 大概11點30左右,有同事給我反饋是調用我的服務陸續(xù)開始有readTime out 產(chǎn)生,導致測試環(huán)境整體數(shù)據(jù)查詢失敗,QA無法進行測試,讓我?guī)兔μ幚硪幌?,于是我登錄上QA的測試機,準備查看一下服務狀態(tài)。

access日志

? ? 先查看了一下tomcat的access日志發(fā)現(xiàn)10點40之后服務就不對外響應了,第一時間感覺應該是服務僵死了,然后開始排查GC狀態(tài)。


GC排查

? ? ? 1.jstat -gcutil pid 1000

? ? ? ? ? ? 稍微解釋一下這個命令 每隔1秒打印當前jvm進程的內存分配占比及gc信息?,發(fā)現(xiàn)GC信息停滯,整個GC進程已經(jīng)不工作了,于是我認為可能是由于full GC的問題導致stop the world 使GC過程緩慢(當時詢問了一下同事,正巧QA同事在進行大數(shù)據(jù)量下載測試),于是我決定導出當前dump信息進行分析

? ? ? 2.jmap -dump:format=b,file=xxx.hprof pid?

? ? ? ? ? ? 發(fā)現(xiàn)連接不上,于是使用-F 強制dump,dump開始進行,但進行到一半左右,報出異常

?發(fā)現(xiàn)dump不下來之后,查了一下異常信息,發(fā)現(xiàn)很多說是由于JDKbug引起,但感覺沒有一個人說明白到底是為什么(這個我沒有查出來原因,歡迎大家給出方案,我也會繼續(xù)查一下),dump失敗之后我決定先看一下是否有線程hang住,于是用jstack查看。

3.jstack -F pid?

? ? 發(fā)現(xiàn)除了socket線程之后,其他線程都blocked,感覺這個問題還是沒有定位,決心繼續(xù)dump內存信息(其實這個時候思想已經(jīng)出問題了,正確做法是這個時候應該使用top查看是不是有線程占用了cpu導致其他線程無法繼續(xù)運行)


但是dump信息一直導不出來,到了這個時候有點懵圈了 三板斧打完,沒了,此時已經(jīng)是午飯過后(公司吃飯比較早 當然是先吃完飯了再回來排查),一看時間已經(jīng)2點20左右了,此時QA同學又開始催了,本著要弄明白再重啟的決心,我決定場外求助大佬,正巧一個大佬過來商量工作,于是在商量完之后果斷向他請教這個問題,大佬看完dump不下來之后認為是JDK出現(xiàn)的bug(不要問我為什么 我也不知道為什么),于是問我能不能使用jstack,我說可以,然后大佬決定先用TOP查看一下機器的資源使用情況。

?4.top?

? ? 先使用top命令發(fā)現(xiàn)當前僵死進程占用cpu 99.9%,? ? 然后跟上?top -H -p 發(fā)現(xiàn)有一個線程占用cpu高達98以上,于是感覺是這個線程的問題

5.pstack

? ? pstack 26846(僵死的進程號) 查看進程的線程信息 發(fā)現(xiàn)該線程為jvm線程而非業(yè)務線程,此時大佬給我說這是JDK的一個bug,具體原因他忘記了,這邊有個同事之前遇見過,這個bug會使類卸載失敗,從而導致cpu100%空轉,這個時候我突然想起之前聽同事說過以前我們項目出現(xiàn)過這個問題,當時公司一位大佬幫忙排查并解決之后,還在公司的微信公眾號發(fā)表了一篇文章,于是感覺去看了一下,發(fā)現(xiàn)原因一模一樣,這邊QA同學將之前出問題的jvm啟動配置原封不動的copy過來,然后啟動了我的服務(所以問題歸納總結感覺還是很有必要)


問題原因及解決

????這個圖我是從大佬的文章中拿的,因為我在解決問題的時候 并沒有保存之前的配置,所以就用了這個圖表達了,但是這2個服務配置是一模一樣的,出問題的服務就是從這個服務copy的配置。

? ? ? Xms? 初始化堆內存大小

? ? ? Xmx 最大堆內存大小 (大小設置為一樣可防止JVM動態(tài)調整影響運行時性能)

? ? ? Xmn 新生代大?。ü俜酵扑]位 3/8 )

? ? ? MetaSpaceSize 初始化元數(shù)據(jù)區(qū)大小

? ? ? MaxMetaSpaceSize? 元數(shù)據(jù)區(qū)最大大小

? ? ? noclassgc 不進行類卸載

? ? ? UseConcMarkSweep 使用cms進行老年代gc (附帶 jdk8中使用cms的時候 新生代默認為parNew)

? ? 上面指定了noclassgc 即不進行類卸載,但是在JDK中還有一個參數(shù)也可以指定是否進行類卸載即

?? ?CMSClassUnloadingEnable,而且在JDK8之后默認該參數(shù)為true 即進行類卸載,所以當同時指定這2個參數(shù)會發(fā)生類卸載失敗的情況(在特定版本中 如8u40),解決的辦法也很簡單 即不設置noclassgc即可,當然如果你想使用這個參數(shù)的話 建議升級JDK版本,在8u60之后 問題已經(jīng)解決,當它設置為false的時候cmsClassUnloadingEnable也會默認設置為false,保證處于同一邏輯下。

? ? 問題解決方案及原因參照我司JAVA大佬的博客-感興趣的可以微信公眾號 -貝殼產(chǎn)品技術 文章為《謎!JVM為何僵死》

總結? ?

? ? 其實之前也排查過一些簡單的gc問題 但是感覺這方面積累還不夠,加上自己水平還是比較菜(對,所以我的名字就叫菜菜子),處理一個問題還是需要很久,而且對知識總結較少,之后也會慢慢開始做一些總結性的東西,其實簡書我也開通很久了,也是第一篇文章,加油吧,777777(就這樣吧 ,我感覺就這樣)。? ??

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容