這篇文章主要介紹java中依賴包濫用System.gc()導(dǎo)致的頻繁Full GC怎么辦,文中介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們一定要看完!
專業(yè)從事網(wǎng)站設(shè)計(jì)、做網(wǎng)站,高端網(wǎng)站制作設(shè)計(jì),微信小程序定制開發(fā),網(wǎng)站推廣的成都做網(wǎng)站的公司。優(yōu)秀技術(shù)團(tuán)隊(duì)竭力真誠服務(wù),采用H5技術(shù)+CSS3前端渲染技術(shù),響應(yīng)式網(wǎng)站設(shè)計(jì),讓網(wǎng)站在手機(jī)、平板、PC、微信下都能呈現(xiàn)。建站過程建立專項(xiàng)小組,與您實(shí)時在線互動,隨時提供解決方案,暢聊想法和感受。
業(yè)務(wù)部門的一個同事遇到個奇怪的 Full GC 問題,有個服務(wù)遷移到新的應(yīng)用后,一直頻繁 Full GC。新應(yīng)用機(jī)器的配置是 4c 8g,老應(yīng)用是 4c 4g,老應(yīng)用 GC 都很正常,并且代碼沒有變更,所以比較奇怪。
問題的現(xiàn)象是,從監(jiān)控圖上看一直有大量的 Full GC
遇到這個問題,一般都是先看看各個區(qū)的內(nèi)存占用情況:
從監(jiān)控圖上看 Old Gen、Young Gen、Perm Gen,沒什么問題,不會觸發(fā) Full GC,當(dāng)然這里看各個 Gen 是否會觸發(fā) Full GC 需要結(jié)合 JVM 參數(shù)配置來看。
順便也看了下 GC 日志,一直狂暴 CMS GC 日志,而且可以看到老年代使用空間也不大,細(xì)心可以發(fā)現(xiàn),大量的 CMS GC 中夾雜著 Young、Perm 區(qū)的回收,所以其實(shí)是 Full GC。GC 日志如下:
老應(yīng)用的 JVM 參數(shù)配置
新應(yīng)用的 JVM 參數(shù)配置
通過上面的觀察,再根據(jù)一般觸發(fā) CMS GC 幾個可能性:
Old Gen 使用達(dá)到一定的比率,默認(rèn)為92%,這里看 CMSInitiatingOccupancyFraction=80%,而實(shí)際才使用 2%(看監(jiān)控圖表)不到,所以排除這種情況。
配置了 CMSClassUnloadingEnabled,且 Perm Gen 的使用達(dá)到一定的比率默認(rèn)為 92%,這里看 CMSInitiatingPermOccupancyFraction=80%,而實(shí)際才使用 30%(看監(jiān)控圖表)不到,所以排除這種情況。
配置了 ExplictGCInvokesConcurrent 且未配置 DisableExplicitGC 的情況下顯示調(diào)用了 System.gc()。
Hotspot 自己根據(jù)估計(jì)決定是否要觸法,如 CMS 悲觀策略,這類可以通過 GC 日志分析。
大致判斷很可能是 System.gc() 導(dǎo)致的問題,但是怎么定位調(diào)用 System.gc() 的代碼呢? 當(dāng)時就想如果是 System.gc() 引起的頻繁 Full GC,jstack 線程堆棧應(yīng)該能看到一些信息,果不其然,確實(shí)通過線程堆棧找到了。
jstack 作用非常大,很多問題都能從這里發(fā)現(xiàn),而且比較輕量,對應(yīng)用基本無影響。某次的 jstack 信息只代表那個時刻的線程堆棧,有時只看一個 jstack 信息可能看不出什么問題,一般可以多 jstack 幾次,然后對比去看,基本就能發(fā)現(xiàn)一些問題。 (當(dāng)然該問題,也可能不是頻繁的 Full GC,可能通過 jstack 定位不到問題,可以 jstat -gccause pid 1000,來查看 gc 原因。)
很明顯,是由于 jxl 這個包中的 close 方法顯示調(diào)用了 System.gc() 導(dǎo)致的問題。
跟了下代碼,自然確實(shí)存在這段代碼,不過有個設(shè)置開關(guān),可以 disable 這個功能,所以在使用的時候可以設(shè)置 setGCDisabled(true),關(guān)閉觸發(fā) System.gc()。
但是為什么老應(yīng)用沒有問題呢,主要是因?yàn)樗?-XX:+DisableExplicitGC,屏蔽了 System.gc() 動作,新應(yīng)用的 JVM 沒有這個配置。
可能大家還有個疑問,都知道 System.gc() 會觸發(fā) Full GC,那為什么一直進(jìn)行 CMS GC(通過GC日志)呢? 主要是因?yàn)檫@個參數(shù) -XX:+ExplicitGCInvokesConcurrent,打開此參數(shù)后,會做并行 Full GC,只有配置 -XX:+UseConcMarkSweepGC 這個參數(shù),該參數(shù)才會生效。因此,System.gc() 時 Old 區(qū)會進(jìn)行 CMS GC,可提高 Full GC 效率。
以上是“java中依賴包濫用System.gc()導(dǎo)致的頻繁Full GC怎么辦”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對大家有幫助,更多相關(guān)知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!