JVM内存参数配置
很多优化无非就是让短期存活的对象尽量都留在survivor里,不要进入老年代,这样在minor gc的时候这些对象都会被回收,不会进到老年代从而导致full gc。
Spring Boot程序的JVM参数设置格式(Tomcat启动直接加载bin目录下catalina.sh文件里,注:X越多的,说明越不稳定,可能在后期版本不使用了):
java ‐Xms2048M ‐Xmx2048M ‐Xmn1024M ‐Xss512K ‐XX:MetaspaceSize=256M ‐XX:MaxMetaspaceSize=256M ‐jar microservice‐eurek a‐server.jar
堆配置:
‐Xms:设置初始化java堆的大小
‐Xmx:设置最大java堆的大小
‐Xmn:设置新生代堆的大小
-XX:+/-UseTLAB:设定虚拟机是否使用TLAB(JVM默认会开启-XX:+UseTLAB)。
-XX:TLABSize:指定TLAB大小。
TLAB(本地线程分配缓冲):是对象在分配内存空间时,解决并发问题的一种方法。可看JVM内存分配
-XX:+UseAdaptiveSizePolicy:堆的eden区和survivor区分配比例变化,默认开启。因为堆的eden区和survivor to 和survivor from 空间比例是8:1:1,开启当前参数,会让比例自动变化。关闭是:-XX:-UseAdaptiveSizePolicy
XX:SurvivorRatio:新生代中Eden区域和Survivor区域(From幸存区或To幸存区)的比例,默认为8,也就是说Eden占新生代的8/10,From幸存区和To幸存区各占新生代的1/10
栈设置:
‐Xss:设置每个线程栈的大小。
注意:当程序进行无限制递归是,会存在栈溢出。-Xss设置的越小,能递归层次就越少。(StackOverflowError),因为JVM每一次递归调用,都会开启一个新的栈空间。
-XX:+DoEscapeAnalysis:开启对象逃逸分析,(-XX:-DoEscapeAnalysis 可进行关闭),jdk7默认开启
-XX:+EliminateAllocations:开启标量替换,jdk7后默认开启,与逃逸分析配合使用。优化对象回收,减少gc。
-XX:PretenureSizeThreshold :堆中对 对象是大对象定义的大小。因为大对象在eden区如果没有被gc回收,会直接到老年代,不走survivor区。此参数只能用于Serial和ParNew回收器。
方法区:
‐XX:MetaspaceSize:指定方法区出发Full GC的初始阈值(方法区无固定初始大小),以字节为单位,默认是21M,达到该值就会触发Full GC进行类型卸载,同时收集器会对该值进行调整:如果释放了大量空间,就适当降低该值;如果释放了很少的空间,那么在不超过 -XX:MaxMetaspaceSize(如果设置了的话)的情况下,适当提高该值。这个跟早期jdk版本的-XX:PermSize参数意思不一样。
‐XX:MaxMetaspaceSize:设置方法区最大值,默认是-1,即不限制,或者说只受本地内存大小限制。
由于调整元空间的大小需要Full GC,这是非常昂贵的操作,如果应用在启动的时候发生了大量Full GC,通常都是由于永久代(元空间)发生了大小调整,基于这种情况,一般建议在JVM参数中将MetaspaceSize和MaxMetaspaceSize设置成一样的值,并设置的比初始化值要大,对于8G物理内存的机器来说,一般会将这两个值都设置成256M。
-XX:PermSize:代表永久代的初始容量。
对象头
-XX:+UseCompressedOops:启动指针压缩,默认开启,关闭是-XX:-UseCompressedOops,4g及以下内存自动不走指针压缩。可看JVM内存分配
GC配置
-XX:MaxTenuringThreshold:对象进入GC需要满足的年龄阈值。最大15,因为对象头是中的gc回收年龄位数限制。
-XX:TargetSurvivorRatio:设置survivor区中需要判断对象动态年龄的内存大小比例。比如当配置为50时,表示当前的survivor区中的对象,从年龄1+年龄2+年龄3+年龄n等对象总和超过了当前survivor区的50%的空间,此时会把年龄n(包含)级以上的对象都放入老年代,一般是minor gc后触发
-XX:-HandlePromotionFailure:老年代空间分配担保机制,因为每次年轻代Minor gc之前都会计算老年代剩余空间是否小于年轻代里现有的所有对象大小之和(包括垃圾对象),如果小于且配置了此配置,则会计算当前老年代大小是否小于历史每次minor gc后进入老年代的对象的平均大小,是,进行full gc,后进行 minor gc(是的,会进行两次);否:进行minor gc。
-XX:+UseSerialGC:年轻代使用SerialGC收集器
-XX:+UseSerialOldGC:老年代使用SerialGC收集器
-XX:+UseParallelGC:年轻代使用Parallel Scavenge收集器
-XX:+UseParallelOldGC:老年代使用Parallel old收集器。
-XX:+UseParNewGC:年轻代使用ParNew 收集器
-XX:+UseConcMarkSweepGC:老年代使用CMS收集器
CMS的相关核心参数
-XX:+UseConcMarkSweepGC:启用cms
-XX:ConcGCThreads:并发的GC线程数
-XX:+UseCMSCompactAtFullCollection:FullGC之后做压缩整理(减少碎片)
-XX:CMSFullGCsBeforeCompaction:多少次FullGC之后压缩一次,默认是0,代表每次FullGC后都会压缩一次
-XX:CMSInitiatingOccupancyFraction: 当老年代使用达到该比例时会触发FullGC(默认是92,这是百分比)
-XX:+UseCMSInitiatingOccupancyOnly:只使用设定的回收阈值(-XX:CMSInitiatingOccupancyFraction设定的值),如果不指定,JVM仅在第一次使用设定值,后续则会自动调整
-XX:+CMSScavengeBeforeRemark:在CMS GC前启动一次minor gc,降低CMS GC标记阶段(也会对年轻代一起做标记,如果在minor gc就干掉了很多对垃圾对象,标记阶段就会减少一些标记时间)时的开销,一般CMS的GC耗时 80%都在标记阶段
-XX:+CMSParallellnitialMarkEnabled:表示在初始标记的时候多线程执行,缩短STW
-XX:+CMSParallelRemarkEnabled:在重新标记的时候多线程执行,缩短STW;
G1收集器参数设置
-XX:+UseG1GC:使用G1收集器
-XX:ParallelGCThreads:指定GC工作的线程数量
-XX:G1HeapRegionSize:指定分区大小(1MB~32MB,且必须是2的N次幂),默认将整堆划分为2048个分区
-XX:MaxGCPauseMillis:目标暂停时间(默认200ms)
-XX:G1NewSizePercent:新生代内存初始空间(默认整堆5%,值配置整数,默认就是百分比)
-XX:G1MaxNewSizePercent:新生代内存最大空间
-XX:TargetSurvivorRatio:Survivor区的填充容量(默认50%),Survivor区域里的一批对象(年龄1+年龄2+年龄n的多个年龄对象)总和超过了Survivor区域的50%,此时就会把年龄n(含)以上的对象都放入老年代
-XX:MaxTenuringThreshold:最大年龄阈值(默认15)
-XX:InitiatingHeapOccupancyPercent:老年代占用空间达到整堆内存阈值(默认45%),则执行新生代和老年代的混合收集(MixedGC),比如我们之前说的堆默认有2048个region,如果有接近1000个region都是老年代的region,则可能就要触发MixedGC了
-XX:G1MixedGCLiveThresholdPercent(默认85%) region中的存活对象低于这个值时才会回收该region,如果超过这个值,存活对象过多,回收的的意义不大。
-XX:G1MixedGCCountTarget:在一次回收过程中指定做几次筛选回收(默认8次),在最后一个筛选回收阶段可以回收一会,然后暂停回收,恢复系统运行,一会再开始回收,这样可以让系统不至于单次停顿时间过长。
-XX:G1HeapWastePercent(默认5%): gc过程中空出来的region是否充足阈值,在混合回收的时候,对Region回收都是基于复制算法进行的,都是把要回收的Region里的存活对象放入其他Region,然后这个Region中的垃圾对象全部清理掉,这样的话在回收过程就会不断空出来新的Region,一旦空闲出来的Region数量达到了堆内存的5%,此时就会立即停止混合回收,意味着本次混合回收就结束了。
其他
-XX:+PrintGC:开启GC日志打印
-XX:+PrintGCDetails:答应GC详情
- 没写完,后期继续,晚了,睡觉
JVM优化理念
尽可能让对象都在新生代里分配和回收,尽量别让太多对象频繁进入老年代,避免频繁对老年代进行垃圾回收,同时给系统充足的内存大小,避免新声代频繁的进行垃圾回收。