在開始以前先記錄一個我碰到的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
jps:查看idea platform的進程IDspa
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狀況。