众所周知IDEA的启动是很慢的,最近看了书上对Eclipse启动进行调优的案例,也想对IDEA调整一下,首先贴出来IDEA默认的参数:
-Xms128m
-Xmx750m
-XX:ReservedCodeCacheSize=240m
-XX:+UseConcMarkSweepGC
-XX:SoftRefLRUPolicyMSPerMB=50
-ea
-Dsun.io.useCanonCaches=false
-Djava.net.preferIPv4Stack=true
-XX:+HeapDumpOnOutOfMemoryError
-XX:-OmitStackTraceInFastThrow
-Dawt.useSystemAAFontSettings=lcd
-Dsun.java2d.renderer=sun.java2d.marlin.MarlinRenderingEngine
-Dide.no.platform.update=true
下载VisualVM(在Ubuntu上可以直接用apt下载),打开VisualVM,在Tools->Plugins中安装Visual GC插件,然后再启动IDEA,可以从VisualVM左侧的列表中看到对应的程序,双击可以看到右侧的数据:
右侧有Overview、Monitor、Threads、Sampler和Visual GC几个标签,其中Overview中可以看到程序的基本信息和启动参数、环境变量等等;Monitor是几个折线图,用于显示CPU、内存(分为Heap和Metaspace)、Classes和Threads的使用情况或者数量;Visual GC是用图形化的方式显示了Heap的每个空间,如Eden、S0、S1、Old和Metaspace的使用情况,以及它们的空间使用量的变化折线图,和GC的次数、时间等等。在这里我们主要关注Monitor和Visual GC标签。
先在Monitor标签里面看一下内存的使用情况,如下面两张图所示:
可以看到,在虚拟机的启动过程中Heap和Metaspace都扩容了好几次,特别是Metaspace空间几乎每时每刻都在扩容。对于Metaspace空间来说,每次达到MetaspaceSize之后都会导致一次Full GC,查看是否能够卸载一些不使用的类,之后再根据此次GC的回收情况进行扩容,但是从可以看到这些GC是没有效果的,它们只进行了扩容,所以可以通过设置一个较大的初始MetaspaceSize参数来进行优化。同样的,Heap也可以设置一个较大的初始值来避免内存扩展,另外可以提高新生代的大小避免频繁的Minor GC。
另外,此次运行的其他数据如下:
可以看到进行了90多次GC,其中84次Minor GC和12次Full GC。
接下来将IDEA的内存参数设置成如下:
-Xms1024m //设置堆的最小值
-Xmx2048m //设置堆的最大值
-Xmn512m //设置新生代大小
-XX:MetaspaceSize=256m //设置初始Metaspace空间的大小
再次启动后数据截图如下:
可以看到GC的次数大大降低,但是还是有一次Full GC,加上参数:
-XX:+PrintGCDetails
-verbose:gc
-Xloggc:/home/jia/gc.log
之后再次启动程序可以看到gc.log
文件中有一行:
20.642: [Full GC (System.gc()) 20.642: [CMS: 76552K->109335K(524288K), 0.5154270 secs] 426201K->109335K(996160K), [Metaspace: 144611K->144611K(1181696K)], 0.5156352 secs] [Times: user=0.50 sys=0.02, real=0.52 secs]
是由于IDEA不知道在哪调用了System.gc()
导致,在内存做了调整后这种显式的GC已经不再需要了,去掉它可以加上参数:-XX:+DisableExplicitGC
来搞定。之后的GC时间可以控制在0.7s左右。
还有一个很耗时的操作是字节码验证,去掉字节码验证的参数是-Xverify:none
,去掉前和去掉后的对比如图所示:
可以看到效果还是很显著的,类加载的时间从45s降低到了30s。所以最终的参数是:
-Xms1024m
-Xmx2048m
-Xmn512m
-XX:ReservedCodeCacheSize=240m
-XX:+UseConcMarkSweepGC
-XX:SoftRefLRUPolicyMSPerMB=50
-ea
-Dsun.io.useCanonCaches=false
-Djava.net.preferIPv4Stack=true
-XX:+HeapDumpOnOutOfMemoryError
-XX:-OmitStackTraceInFastThrow
-Dawt.useSystemAAFontSettings=lcd
-Dsun.java2d.renderer=sun.java2d.marlin.MarlinRenderingEngine
-Xverify:none
-XX:MetaspaceSize=256m
-XX:+DisableExplicitGC
另外,如果喜欢长期不关闭电脑和IDEA的同学可以加上参数-server
,这样jvm会使用C2编译器来编译成机器码,做出的优化会更加激进,也更加高效,不过需要在启动时花费更长的时间来编译代码。