记录一次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状况。

相关文章
相关标签/搜索