51

记录一次Metaspace扩容引发FGC的调优总结

 4 years ago
source link: https://www.tuicool.com/articles/B3A7Nnf
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

开始之前

在开始之前先记录一个我碰到的jvm调优的坑。那就是…

为啥我配置到idea64exe.vmoptions中的参数没有生效???

由于之前一直是在mac上开发,本地开发时当需要优化jvm参数的时候直接去idea的安装目录里修改idea.vmoptions就可以了,换到windows以后想当然的也这么改,但是发现似乎我配置的参数并没有生效, what‘s the f***?探索了一番终于发现了问题所在。

windows是基于用户登录的,idea会为每个用户在当前用户根目录下创建一份配置信息,所以在idea安装目录下修改idea.vmoptions是不生效的,如图:

MJneqqn.png!web

UfABZnb.png!web

不知道管理员用户登录的话是不是就可以直接修改idea安装目录的ideaexe.vmoptions了,有一个很简单的方法判断你当前的idea项目使用的是哪里的配置信息。

RZr2QrF.png!web

发现问题

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的那种。

定位原因

  1. jps:查看idea platform的进程ID

  2. jstat -gcutil pid 3s:查看进程垃圾回收情况

JJVZJb3.png!web

从上图可以看出,刚开始YGC和FGC都很健康,但随着我打开的项目越来越多,FGC开始飙升,直接导致了页面明显的卡顿,我试着关掉了几个项目,只保留一个,FGC慢慢变小,分析上图可以看出,M的占比随着FGC略有下降,从93.7%下降到93.2%左右,推测可能是Metaspace扩容导致的FGC。

确认原因

通过jstat -gc pid 3s:可以查看metaspace具体使用情况,下图可以看出metaspace发生了扩容。

VzeqI37.png!web

更简单的是,通过命令jvisualvm,打开Java VisualVM查看mataspace具体使用大小。

ERFvY3v.png!web

果然,当我同时打开多个项目时,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情况。

ieAbeq2.png!web

这次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情况:

ryMzuqB.png!web

上图是我同时开了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情况。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK