您好,登錄后才能下訂單哦!
這篇文章主要介紹java中依賴包濫用System.gc()導(dǎo)致的頻繁Full GC怎么辦,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!
業(yè)務(wù)部門的一個(gè)同事遇到個(gè)奇怪的 Full GC 問(wèn)題,有個(gè)服務(wù)遷移到新的應(yīng)用后,一直頻繁 Full GC。新應(yīng)用機(jī)器的配置是 4c 8g,老應(yīng)用是 4c 4g,老應(yīng)用 GC 都很正常,并且代碼沒(méi)有變更,所以比較奇怪。
問(wèn)題的現(xiàn)象是,從監(jiān)控圖上看一直有大量的 Full GC
遇到這個(gè)問(wèn)題,一般都是先看看各個(gè)區(qū)的內(nèi)存占用情況:
從監(jiān)控圖上看 Old Gen、Young Gen、Perm Gen,沒(méi)什么問(wèn)題,不會(huì)觸發(fā) Full GC,當(dāng)然這里看各個(gè) Gen 是否會(huì)觸發(fā) Full GC 需要結(jié)合 JVM 參數(shù)配置來(lái)看。
順便也看了下 GC 日志,一直狂暴 CMS GC 日志,而且可以看到老年代使用空間也不大,細(xì)心可以發(fā)現(xiàn),大量的 CMS GC 中夾雜著 Young、Perm 區(qū)的回收,所以其實(shí)是 Full GC。GC 日志如下:
老應(yīng)用的 JVM 參數(shù)配置
新應(yīng)用的 JVM 參數(shù)配置
通過(guò)上面的觀察,再根據(jù)一般觸發(fā) CMS GC 幾個(gè)可能性:
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 悲觀策略,這類可以通過(guò) GC 日志分析。
大致判斷很可能是 System.gc() 導(dǎo)致的問(wèn)題,但是怎么定位調(diào)用 System.gc() 的代碼呢? 當(dāng)時(shí)就想如果是 System.gc() 引起的頻繁 Full GC,jstack 線程堆棧應(yīng)該能看到一些信息,果不其然,確實(shí)通過(guò)線程堆棧找到了。
jstack 作用非常大,很多問(wèn)題都能從這里發(fā)現(xiàn),而且比較輕量,對(duì)應(yīng)用基本無(wú)影響。某次的 jstack 信息只代表那個(gè)時(shí)刻的線程堆棧,有時(shí)只看一個(gè) jstack 信息可能看不出什么問(wèn)題,一般可以多 jstack 幾次,然后對(duì)比去看,基本就能發(fā)現(xiàn)一些問(wèn)題。 (當(dāng)然該問(wèn)題,也可能不是頻繁的 Full GC,可能通過(guò) jstack 定位不到問(wèn)題,可以 jstat -gccause pid 1000,來(lái)查看 gc 原因。)
很明顯,是由于 jxl 這個(gè)包中的 close 方法顯示調(diào)用了 System.gc() 導(dǎo)致的問(wèn)題。
跟了下代碼,自然確實(shí)存在這段代碼,不過(guò)有個(gè)設(shè)置開(kāi)關(guān),可以 disable 這個(gè)功能,所以在使用的時(shí)候可以設(shè)置 setGCDisabled(true),關(guān)閉觸發(fā) System.gc()。
但是為什么老應(yīng)用沒(méi)有問(wèn)題呢,主要是因?yàn)樗?-XX:+DisableExplicitGC,屏蔽了 System.gc() 動(dòng)作,新應(yīng)用的 JVM 沒(méi)有這個(gè)配置。
可能大家還有個(gè)疑問(wèn),都知道 System.gc() 會(huì)觸發(fā) Full GC,那為什么一直進(jìn)行 CMS GC(通過(guò)GC日志)呢? 主要是因?yàn)檫@個(gè)參數(shù) -XX:+ExplicitGCInvokesConcurrent,打開(kāi)此參數(shù)后,會(huì)做并行 Full GC,只有配置 -XX:+UseConcMarkSweepGC 這個(gè)參數(shù),該參數(shù)才會(huì)生效。因此,System.gc() 時(shí) Old 區(qū)會(huì)進(jìn)行 CMS GC,可提高 Full GC 效率。
以上是“java中依賴包濫用System.gc()導(dǎo)致的頻繁Full GC怎么辦”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。