記錄一次Metaspace擴容引起FGC的調優總結

開始以前

  在開始以前先記錄一個我碰到的jvm調優的坑。那就是…java

爲啥我配置到idea64exe.vmoptions中的參數沒有生效???windows

  因爲以前一直是在mac上開發,本地開發時當須要優化jvm參數的時候直接去idea的安裝目錄裏修改idea.vmoptions就能夠了,換到windows之後想固然的也這麼改,可是發現彷佛我配置的參數並無生效, what‘s the f***?探索了一番終於發現了問題所在。jvm

  windows是基於用戶登陸的,idea會爲每一個用戶在當前用戶根目錄下建立一份配置信息,因此在idea安裝目錄下修改idea.vmoptions是不生效的,如圖:ide

  不知道管理員用戶登陸的話是否是就能夠直接修改idea安裝目錄的ideaexe.vmoptions了,有一個很簡單的方法判斷你當前的idea項目使用的是哪裏的配置信息。工具

發現問題

  ok,如今終於能夠優化咱們的jvm參數了,下面是一套我常常用的參數,在我之前開發的時候基本都是用這套參數,我也就直接複製到了idea64exe.vmoptions。優化

-Xms1024m
-Xmx1024m
-Xmn512m
-XX:MetaspaceSize=256m
-XX:MaxMetaspaceSize=256m
-XX:ReservedCodeCacheSize=512m
-XX:+UseConcMarkSweepGC
-XX:SoftRefLRUPolicyMSPerMB=50
-ea
-Dsun.io.useCanonCaches=false
-Djava.net.preferIPv4Stack=true
-XX:+HeapDumpOnOutOfMemoryError
-XX:-OmitStackTraceInFastThrow

  保存重啓idea之後,開一個項目,嗯,沒啥感受,一切正常。開兩個項目,嗯,怎麼有點卡呢。又開了一個項目,噩夢開始了,idea開始爆卡,點一下卡2s的那種。idea

定位緣由

  1. jps:查看idea platform的進程IDspa

  2. jstat -gcutil pid 3s:查看進程垃圾回收狀況.net

 

  從上圖能夠看出,剛開始YGC和FGC都很健康,但隨着我打開的項目愈來愈多,FGC開始飆升,直接致使了頁面明顯的卡頓,我試着關掉了幾個項目,只保留一個,FGC慢慢變小,分析上圖能夠看出,M的佔比隨着FGC略有降低,從93.7%降低到93.2%左右,推測多是Metaspace擴容致使的FGC。命令行

確認緣由

  經過jstat -gc pid 3s:能夠查看metaspace具體使用狀況,下圖能夠看出metaspace發生了擴容。

  更簡單的是,經過命令jvisualvm,打開Java VisualVM查看mataspace具體使用大小。

  果真,當我同時打開多個項目時,metaspace發生了擴容,而且最終mataspace的使用量達到了接近250M,幾乎達到了上面我配置的參數-XX:MetaspaceSize=256m,因而我將上面配置中關於mataspace的參數刪掉。

-Xms1024m
-Xmx1024m
-Xmn512m
-XX:ReservedCodeCacheSize=512m
-XX:+UseConcMarkSweepGC
-XX:SoftRefLRUPolicyMSPerMB=50
-ea
-Dsun.io.useCanonCaches=false
-Djava.net.preferIPv4Stack=true
-XX:+HeapDumpOnOutOfMemoryError
-XX:-OmitStackTraceInFastThrow

   再次jstat -gcutil pid 3s查看GC狀況。

  此次FGC狀況大有改善,隨着我開的項目愈來愈多,FGC也只是從6次漲到了8次。至此,問題基本就解決了,但若是隻是這樣的話,我寫這篇筆記的意義就不大了,接下來的纔是重點。

深刻探究

  我嘗試從新添加了mataspace的參數,以下:

-Xms1024m
-Xmx1024m
-Xmn512m
-XX:MetaspaceSize=384m
-XX:MaxMetaspaceSize=384m
-XX:ReservedCodeCacheSize=512m
-XX:+UseConcMarkSweepGC
-XX:SoftRefLRUPolicyMSPerMB=50
-ea
-Dsun.io.useCanonCaches=false
-Djava.net.preferIPv4Stack=true
-XX:+HeapDumpOnOutOfMemoryError
-XX:-OmitStackTraceInFastThrow

 

  再次jstat -gcutil pid 3s查看GC狀況:

  上圖是我同時開了5個項目的GC狀況,FGC只有1次,這纔是讓我以爲困惑的地方,也就是說當我設置了MetaspaceSize=384m和不設置的時候,是有區別的,在網上看了不少關於mataspace的文章,我發現本身一直以來都沒有搞懂-XX:MetaspaceSize=256M的真正含義,這個配置的含義並非初始化元數據區大小爲256m,而僅僅表示的是觸發FGC的閾值,至於配置和不配置的區別,也就很明顯了,這個知識點在書上看到過可是沒放在心上,在實際碰到問題的時候才恍然大悟。

  Metaspace因爲使用不斷擴容到-XX:MetaspaceSize參數指定的量,就會發生FGC;且以後每次Metaspace擴容均可能會發生FGC。

  咱們知道Metapsace是在jdk8中引入的,以前叫permGen,就是咱們所說的永久代。在jdk8之前,咱們配置-XX:PermSize=256m,那就是說初始化一塊256m的內存做爲永久代。可是mataspace就不同了,很明顯,mataspace要比perm高級的多。

總結

  • 若是沒有配置-XX:MetaspaceSize,那麼觸發FGC的閾值是21807104(約20.8m)。

  • 若是配置了-XX:MetaspaceSize,那麼觸發FGC的閾值就是配置的值。

  • 配置比不配置好,實際開發時,能夠先開幾個項目查看一下metaspace大概佔用多少內存,這個跟項目大小和複雜度有關,再根據實際狀況配置-XX:MetaspaceSize。

查看當前java進程,通常用來查找進程ID(PID)

  • jps:查看當前java進程及PID
  • jps -l:輸出主類或者jar的徹底路徑名
  • jps -v:輸出jvm參數

動態查看gc狀況

  • jstat -gc pid 3s: 每隔3s打印當前pid進程的堆內存詳細信息
  • jstat -gcutil pid 3s: 每隔3s打印當前pid進程的堆內存整體GC統計信息

可視化工具jvisualvm

  命令行直接輸入jvisualvm可打開可視化工具,動態查看java進程內部詳細信息

結合以上3種途徑,能夠查看java進程的詳細使用狀況和GC狀況。

相關文章
相關標籤/搜索