为什么需要调优
前提
好马配好鞍,好车配好发动机。比如超级跑车上给安装一个时风三轮车的发动机是十分不合理的。JVM调优主要是根据所选的垃圾收集器,对一些参数合理性的优化,以确保程序在JVM中能以最优的方式运行。
调优场景及实战
结合作者公司实际场景来给大家介绍参数如何设置,公司做的产品互联网金融方面的,要求支持高并发,垃圾收集器选择的是CMS(Concurrent Mark Sweep),这个收集器的好处是并发收集,停顿低。但是缺点也很明显CPU敏感,浮动垃圾,产生内存碎片。这块就不过多解释这几个名词的意思,接下来进入正题,我们的生产环境上是如何合理配置参数的。首先我们采用的配置方式是把这些参数都写入环境变量中,项目启动前会先加载这个脚本,将参数信息设置到环境变量中,然后执行启动脚本。下面是参数的详细介绍
-
-Xms -Xmx -Xss
Xms:JVM启动时申请的最小堆内存大小,当空余堆内存大于70%,JVM会减少堆内存直到最小限制
Xmx:JVM启动时申请的最大堆内存大小,当空余堆空间小于40%,JVM会增大堆内存直到最大限制
通常情况下为了防止内存抖动(减小或者增大会有一定的性能开销)Xms和Xmx一般设置成相同。Xss:每个线程的堆栈大小,一般根据应用的线程所需内存大小进行调整。大多数情况下设置为1M就可以了
-
-XX:+UseBiasedLocking
是否开启偏向锁,默认是开启的,有一些项目多线程之间竞争锁资源比较频繁,所以会禁用偏向锁。
-
-XX:PermSize -XX:MaxPermSize(JDK1.8已经无效)
PermSize:JVM初始分配的非堆内存(PS:非堆内存一般指方法区)
MaxPermSize:JVM最大允许分配的非堆内存,按需分配
JVM官方文档中提到过 ,非堆内存区是可以选择不被java垃圾回收机制处理的地方。不合理的配置会产生 OutOfMemoryError:PermGen space,这个是java中常见的OOM之一。举个产生会产生此异常的例子,需要加载很多class到容器中。
-
-XX:+DisableExplicitGC
DisableExplicitGC:开启会自动将System.gc()调用转换成一个空操作。目的为了防止有人在代码中进行调用,从而会产生Full GC。
-
-XX:+UseConcMarkSweepGC
UseConcMarkSweepGC:设置年老代为并发收集,通俗来说就是使用CMS垃圾收集器
-
+UseParNewGC
UseParNewGC:设置年轻代为并行收集。可与CMS收集同时使用。一般高并发的项目中都会采用CMS+ UseParNew的方式来配置垃圾收集器
-
-XX:+CMSParallelRemarkEnabled
CMSParallelRemarkEnabled:开启并行收集,降低标记停顿
-
-XX:+UseCMSCompactAtFullCollection
UseCMSCompactAtFullCollection:打开对老年代的压缩。可能会影响性能,但是可以消除内存碎片。
-
-XX:LargePageSizeInBytes
LargePageSizeInBytes:设置内存页的大小,一般不易设置过大,会影响到Perm的大小
-
-XX:+UseFastAccessorMethods
UseFastAccessorMethods:原始类型的快速优化
-
-XX:+UseCMSInitiatingOccupancyOnly
UseCMSInitiatingOccupancyOnly: 使用手动定义初始化定义开始CMS收集,避免hostspot虚拟机来自行触发CMS GC
-
-Djava.awt.headless=true
Djava.awt.headless:一般开启,系统的配置模式,说得是如果系统可能缺少显示设备、键盘或鼠标这些外设的情况下可以使用该模式。
-
-Djava.security.egd=file:/dev/./urandom
Djava.security.egd:加快随机数的产生过程,因为Tomcat的会话ID都是随机生成的,配置此项后可以加快项目启动速度,
总结
JVM参数虽然众多,但基本上大多数都不需要自行修改,JDK新版本在优化后也会大批量减少很多参数。
最后说一句,大家发现有配置不合理的地方可以提出来,一块讨论,以上纯手敲,码字不易,且读且珍惜。