最近线上部署服务的时候,出现了内存占用率高,资源不够导致部分服务频繁崩溃的原因,因为项目是微服务架构,起初认为是微服务占用内存过大,第一反应是增加硬件内存的措施,后来部门大佬查看服务器运行情况,然后抛给我一串JVM参数,加上参数,内存占用率果然得到了明显的提升,接下来主要是来介绍一下JVM相关的调优参数,互相学习。
大佬的JVM调优参数:
nohup java -Xms2048m -Xmx2048m -Xmn1024m -Xss1024K -XX:PermSize=2048m -XX:MaxPermSize=2048m -XX:ParallelGCThreads=8 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+UseCMSCompactAtFullCollection -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=10 -XX:CMSInitiatingOccupancyFraction=80 -jar
目前项目用到JDK版本是8,所以以这个版本的JVM作为讲解(之前老版本的JVM参数也会介绍)
-Xms:
代表初始化堆的大小,一般默认是主机物理内存的1/64大小。
-Xmx:
代表堆的最大值。一般默认是主机物理内存的1/4大小。
默认空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制;空余堆内存大于70%时,JVM会减少堆直到-Xms的最小限制。官方建议将-Xms和-Xmx设为一致,避免每次GC之后重新设置堆的大小。
-Xmn:
代表堆中年轻代的大小,堆大小=年轻代+年老代,一般默认年轻代和年老代比值为1:2,可以通过**-XX:NewRatio来设置年轻代和年老代的比值大小,所以一般设置了年轻代的大小,那么年老的大小也基本上确定了,同时 年轻代大小=eden+Survivor, 一般默认为8:1, Survivor区又分为from和to区,两个区的大小为1:1,所以Survivor=1/8eden=from+to,关于eden和Survivor的比例可以通过SurvivorRatio**进行设置,默认是为8.
-XX:PermSize:
代表永久代的大小。
这个配置是java7之前的配置,在java8之后是没有永久代的概念的,用元空间取代了之前的永久代,如果你的JDK版本是8之后的,那么这个参数是没有必要进行设置的。永久代的大小要注意,根据项目情况进行设置,可能会抛出OutOfMemoryError异常。
-XX:ParallelGCThreads:
代表的是GC并行垃圾回收的线程数,一个参数是相对于并行垃圾回收器来进行设定的,因为现在计算机基本上都是多核处理器,并行垃圾回收可以增加GC效率。
XX:+UseConcMarkSweepGC:
设置垃圾回收器类型,这个设置为CMS垃圾回收器,JVM默认的垃圾回收器为SerialGC,注意在JDK7,8,9各个版本默认的垃圾回收期不同
jdk1.7 默认垃圾收集器Parallel Scavenge(新生代)+Parallel Old(老年代)
jdk1.8 默认垃圾收集器Parallel Scavenge(新生代)+Parallel Old(老年代)
jdk1.9 默认垃圾收集器G1
-XX:+UseParNewGC:
设置年轻代为并行收集,JKD5.0以上,JVM会根据系统配置自行设置,所以无需设置此值。
-XX:+UseCMSCompactAtFullCollection:
CMS是一款基于“标记——清除”算法实现的收集器,这意味着收集结束会有大量空间碎片产生,空间碎片过多将会给大对象分配带来很大麻烦,往往表现在老年代有很大空间剩余,但是无法找到连续的空间来分配当前的对象,不得不提前触发一次FullGC。-XX+UseCMSCompactAtFullCollection 在FULL GC的时候, 对年老代的压缩,这个参数默认是开启的,虚拟机设计者还提供了另外一个参数如下**-XX:CMSFullGCsBeforeCompaction** 这个参数是用于设置执行多少次不压缩的Full GC后跟着来一次带压缩的Full GC,这个参数的默认值为0表示每次Full GC都进行碎片整理。
(此参数从JDK 9开始废弃)
-XX:MaxTenuringThreshold:
这个参数主要是要来判断在年轻代中的对象经历多少次垃圾回收之后进入老年代。 首先创建的新对象是在Eden区中存放的,当经历过一次Minor GC后,如果Survivor区能够存放的话,就放入到Survivor区,MaxTenuringThreshold用来设置将经历多多少次的Minor GC还存活的对象放入到老年代中,这里有一点值得注意,为了能更好地适应不同程序的内存状况,HotSpot虚拟机并不是永远要求对象的年龄必须达到-XX:MaxTenuringThreshold才能晋升老年代,如果在Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代,无须等到-XX:MaxTenuringThreshold中要求的年龄。
XX:CMSInitiatingOccupancyFraction:
表示老年代的空间被占用多少之后会启动垃圾回收机制,在JDK5默认为68%,JDK6默认为92%,这里设置这个原因是因为在垃圾回收的时候,垃圾回收的线程和用户的线程是并发进行的,所以要预留一部分空间来存储用户线程所创建的对象。
这里后面会介绍垃圾回收算法和一下新的垃圾回收器G1。