jdk11-zgc-gc時間不斷增長

1.現(xiàn)象

為了降低gc時間涩澡,我們打算對一批服務安裝jdk11顽耳,使用zgc。在對zgc進行測試期間妙同,發(fā)現(xiàn)隨著程序的運行射富,gc時間越來越長。如下圖所示:

每分鐘gc總耗時

同時進程的gc次數(shù)并沒有發(fā)生太大變化粥帚,如下圖所示:

每分鐘gc總次數(shù)

zgc的 gc.time 只和 GC Roots 相關胰耗,關于zgc可以參考:https://tech.meituan.com/2020/08/06/new-zgc-practice-in-meituan.html

既然gc次數(shù)沒有變多,所以應該是GC Roots 數(shù)量增長

2.原因分析

我們?nèi)ゲ榭唇鼛滋斓膅c日志芒涡,會發(fā)現(xiàn) Subphase: Pause Roots ClassLoaderDataGraph? 這個階段的耗時會不斷增加

gc日志

這時候開始懷疑GC Roots有問題

此時查看metaspace元空間監(jiān)控柴灯,發(fā)現(xiàn)metaspace不斷增長,metaspace里的對象是被認為GC Roots费尽。所以因為metaspace不斷增長赠群,導致GC Roots越來越多,最終導致gc時間越來越長

元空間內(nèi)存占用情況

為什么metasapce空間不斷增長呢旱幼?

metaspace空間主要保存對象類信息乎串,我們查看關于class相關監(jiān)控信息

加載class信息監(jiān)控

可以看到我們程序不斷l(xiāng)oad class,但是沒有unload class,所以導致meta內(nèi)存一直增長

原因大概也就清楚了叹誉,但是此時產(chǎn)生疑問鸯两,為什么程序原先使用jdk8 cms gc算法,沒有這個問題呢长豁。

我們查看一下之前使用cms算法相關監(jiān)控


cms機器監(jiān)控信息

可以看到這臺 cms 機器钧唐,也不斷l(xiāng)oad class,但是他也會 unload class匠襟,所以metaspace一直維持平穩(wěn)

因為我們在使用cms時钝侠,設置了一個jvm參數(shù):CMSClassUnloadingEnabled 。該參數(shù)表示在進行cms酸舍,進行class卸載

3. zgc

為什么zgc不會收 meta:使用的jdk11不支持回收帅韧,jdk12才支持

在JDK11,zgc垃圾回收器目前還只是實驗性的功能啃勉,只支持Linux/x64平臺忽舟。后續(xù)優(yōu)化接改進,短時間內(nèi)無法更新到JDK11中淮阐,所以可能會遇到一些不穩(wěn)定因素叮阅。例如: 1. JDK12支持并發(fā)類卸載功能。2. JDK13將可回收內(nèi)存從4TB支持到16TB泣特。3. JDK14提升穩(wěn)定性的同時浩姥,提高性能。4. JDK15從實驗特性轉(zhuǎn)變?yōu)榭缮a(chǎn)特性 状您。所以對于一些大量使用反射勒叠、動態(tài)代理、CGLIB和Javasist等頻繁自定義類加載器的場景中膏孟,ZGC難以處理Metaspace的巨大內(nèi)存壓力缴饭。

4.為什么metaspace一直升高

我們對運行的進程進行class統(tǒng)計

jcmd {pid} GC.class_stats

加載的class類信息

發(fā)現(xiàn)存在大量的jdk.internal.reflect.GeneratedConstructorAccessor class類

我們對上述的內(nèi)容進行前綴統(tǒng)計,命令如下:

?jcmd {pid} GC.class_stats |awk '{print$13}'|sed? 's/\(.*\)\.\(.*\)/\1/g'|sort |uniq -c|sort -nrk1

class前綴統(tǒng)計

發(fā)現(xiàn) jdk.internal.reflect 包名下的類文件骆莹,占用了很大一部分颗搂,并且隨著程序運行,jdk.internal.reflect這個類文件越來越多幕垦。

這個就是我們在使用jdk反射時丢氢,會自動生成的類字節(jié)碼,被jvm加載進metaspace先改。隨著程序運行疚察,加載類字節(jié)碼越來越多,但是沒有釋放仇奶,導致meta越來越大貌嫡。

5.解決辦法

-Dsun.reflect.inflationThreshold 可以控制通過反射生成字節(jié)碼。(該值表示 反射調(diào)用多少次 才開始生成字節(jié)碼)

當把該參數(shù)這是int 最大值時,說明永不生成字節(jié)碼岛抄。

從stackoverflows摘抄一段話

When using Java reflection, the JVM has two methods of accessing the information on the class being reflected. It can use a JNI accessor, or a Java bytecode accessor. If it uses a Java bytecode accessor, then it needs to have its own Java class and classloader (sun/reflect/GeneratedMethodAccessor class and sun/reflect/DelegatingClassLoader). Theses classes and classloaders use native memory. The accessor bytecode can also get JIT compiled, which will increase the native memory use even more. If Java reflection is used frequently, this can add up to a significant amount of native memory use. The JVM will use the JNI accessor first, then after some number of accesses on the same class, will change to use the Java bytecode accessor. This is called inflation, when the JVM changes from the JNI accessor to the bytecode accessor. Fortunately, we can control this with a Java property. The sun.reflect.inflationThreshold property tells the JVM what number of times to use the JNI accessor. If it is set to 0, then the JNI accessors are always used. Since the bytecode accessors use more native memory than the JNI ones, if we are seeing a lot of Java reflection, we will want to use the JNI accessors. To do this, we just need to set the inflationThreshold property to zero.

If you are on a Oracle JVM then you would only need to set:? -Dsun.reflect.inflationThreshold=2147483647

If you are on IBM JVM, then you would need to set:? ?-Dsun.reflect.inflationThreshold=0

大概意思說:使用java反射别惦,內(nèi)部實現(xiàn)有2種方式,一種是jni夫椭,另一種是生成字節(jié)碼方式掸掸。生成字節(jié)碼方式會占用更多內(nèi)存,但是性能會好一點蹭秋。sun.reflect.inflationThreshold 代表扰付,反射執(zhí)行多少次后,開始使用字節(jié)碼方式仁讨,當我們把這個參數(shù)設置為int最大值羽莺,代表永不使用字節(jié)碼方式,也就沒有內(nèi)存問題了洞豁。

具體原理參考:

https://www.moregeek.xyz/i/880000804235

https://stackoverflow.com/questions/16130292/java-lang-outofmemoryerror-permgen-space-java-reflection

重新加上?-Dsun.reflect.inflationThreshold=2147483647 這個參數(shù)盐固,后來gc.time 次數(shù)就一直穩(wěn)定下來了,并且metaspace空間也不增長了

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末族跛,一起剝皮案震驚了整個濱河市闰挡,隨后出現(xiàn)的幾起案子锐墙,更是在濱河造成了極大的恐慌礁哄,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件溪北,死亡現(xiàn)場離奇詭異桐绒,居然都是意外死亡,警方通過查閱死者的電腦和手機之拨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門茉继,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蚀乔,你說我怎么就攤上這事烁竭。” “怎么了吉挣?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵派撕,是天一觀的道長。 經(jīng)常有香客問我睬魂,道長终吼,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任氯哮,我火速辦了婚禮际跪,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己姆打,他們只是感情好良姆,可當我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著穴肘,像睡著了一般歇盼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上评抚,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天豹缀,我揣著相機與錄音,去河邊找鬼慨代。 笑死邢笙,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的侍匙。 我是一名探鬼主播氮惯,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼想暗!你這毒婦竟也來了妇汗?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤说莫,失蹤者是張志新(化名)和其女友劉穎杨箭,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體储狭,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡互婿,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了辽狈。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片慈参。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖刮萌,靈堂內(nèi)的尸體忽然破棺而出驮配,到底是詐尸還是另有隱情,我是刑警寧澤着茸,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布壮锻,位于F島的核電站,受9級特大地震影響元扔,放射性物質(zhì)發(fā)生泄漏躯保。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一澎语、第九天 我趴在偏房一處隱蔽的房頂上張望途事。 院中可真熱鬧验懊,春花似錦、人聲如沸尸变。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽召烂。三九已至碱工,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間奏夫,已是汗流浹背怕篷。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留酗昼,地道東北人廊谓。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像麻削,于是被迫代替她去往敵國和親蒸痹。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 1呛哟、從編碼到執(zhí)行 解釋執(zhí)行和編譯執(zhí)行是可以混合的叠荠,執(zhí)行次數(shù)多的代碼,會進行 JIT 的編譯扫责,交由操作系統(tǒng)直接執(zhí)行榛鼎。...
    ArthurHC閱讀 328評論 0 2
  • Catalog 1 怎么解決OOM?/ 怎么排查OOM公给?/ JVM調(diào)優(yōu)1.1 JDK自帶工具1.2 阿里開源JVM...
    allen鍋閱讀 341評論 0 1
  • 解決服務器進程退出問題(metaspace溢出) 現(xiàn)象策劃反應服務器進不去,遠程看了一下進程消失了(crash)有...
    landon30閱讀 3,364評論 0 2
  • 運行時數(shù)據(jù)區(qū)域 jdk 1.8之前與之后的內(nèi)存模型有差異借帘,方法區(qū)有變化(https://cloud.tencent...
    陳晨_軟件五千言閱讀 1,216評論 2 12
  • 本文所有內(nèi)容來于:http://stuq.com/a/100ww java代碼是如何執(zhí)行的 java代碼是運行于j...
    良辰美景TT閱讀 2,743評論 0 89