JVM 之参数配置
目录
一、垃圾回收统计信息
java -XX:+PrintFlagsFinal //打印所有的通过-XX:可配置的参数
-verbose:gc //在控制台输出GC情况
-XX:+PrintGCDetails //在控制台输出详细的GC情况
-Xloggc: filepath //将GC日志输出到指定文件中
-XX:+PrintGCTimeStamps //GC日志中的时间戳(JVM启动后的时间间隔)
-XX:+PrintGCDateStamps //指定时间戳(以日期的形式,如 2013-05-04T21:53:59.234+0800)
-XX:+PrintReferenceGC //打印强软弱虚引用的数量,以及清理所用的时长
-XX:+HeapDumpOnOutOfMemoryError //在OOM异常退出时导出堆内存信息dump文件
-XX:HeapDumpPath=/data/log/jvmdump/ //dump文件导出地址,需要提前建好目录
二、空间大小
-Xmx4g //堆内存的最大大小
-Xms4g //堆内存的初始大小
-Xmn1512m //堆内年轻代的大小
-Xss256k //单个线程栈大小,越小可生成线程越多(默认1M)
-XX:NewRatio //设置年轻代和老年代的比值。设为3表示年轻代与老年代比值为1:3
-XX:SurvivorRatio //年轻代中Survivor区与Eden区的比值。设为8表示2*Survivor:Eden=2:8
-XX:PermSize -XX:MaxPermSize //永久代初始大小与最大大小(Java8以前)
-XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256m //元空间首次触发FullGC大小与最大大小,初始默认20.75M(Java8以后)
三、垃圾回收器选用
-XX:+UseSerialGC //只配置此项,则年轻代和老年代都用串行收集器
-XX:+UseParNewGC //年轻代使用ParNew,老年代使用 Serial Old
-XX:+UseParallelGC //年轻代:Paraller Scavenge,老年代:Serial Old
-XX:+UseParallelOldGC //年轻代Paraller Scavenge,老年代Paraller Old
-XX:+UseConcMarkSweepGC //年轻代使用ParNew,老年代的用CMS + Serial Old
-XX:+UseG1GC //使用G1垃圾回收器
-XX:+UseZGC //使用ZGC垃圾回收器
四、其他设置:
-XX:MaxTenuringThreshold //转入老年代的存活次数。如果是0,则直接跳过年轻代进入老年代
-XX:ParallelGCThreads=n //设置并行收集器收集时使用的CPU数。并行收集线程数。
-XX:MaxGCPauseMillis=n //设置并行收集最大暂停时间
-XX:GCTimeRatio=n //设置垃圾回收时间占程序运行时间的百分比。公式为1/(1+n)
-XX:+CMSIncrementalMode //设置为增量模式。适用于单CPU情况。
-XX:ParallelGCThreads=n //设置并发收集器年轻代收集方式为并行收集时,使用的CPU数。并行收集线程数。
-XX:CMSInitiatingOccupancyFraction=75
-XX:+UseCMSInitiatingOccupancyOnly //限制只在老年代达到75%才回收,并开启功能
-XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses
//一个搭配CMS时很好用的JVM参数
//1、只有在使用CMS时才有效。
//2、当调用System.gc()时会用CMS这个并行垃圾回收器去进行回收而不是FullGCC(比如大量使用DirectByteBuffer进行堆外内存操作,需要FGC来回收堆外内存的场景。就可以通过该参数让本来需要FGC才能搞定的事情用CMS GC就可以搞定了)。
//3、除了能唤起并行垃圾回收器,还能卸载类。
五、调优参考
垃圾收集器跟内存大小的大致关系(不精确,需要根据实际环境测试)
Serial —> 几十兆
PS —> 上百兆 ~ 4G
CMS —> 4G ~ 10G
G1 —> 10G~上百G
ZGC —> 4T-16T(JDK13)
摘自互联网:某微服务项目单机并发1000+,CMS GC大概是8天左右一次
-Xms4g -Xmx4g -Xmn1512m -server -Xss256k
-XX:MetaspaceSize=256M
-XX:MaxMetaspaceSize=256m
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps -Xloggc:/data/log/gclog/gc.log
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/data/log/jvmdump/heapdump_$RANDOM.hprof
-XX:+UseConcMarkSweepGC
-XX:+UseParNewGC
-XX:CMSInitiatingOccupancyFraction=75
-XX:+UseCMSInitiatingOccupancyOnly
-XX:+UseCMSCompactAtFullCollection
-XX:CMSFullGCsBeforeCompaction=0 //开启功能,但设为0,代解惑?
-XX:+CMSClassUnloadingEnabled //?
-XX:+TieredCompilation //?
-XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses
参考文章
JVM 源码解读之 CMS GC 触发条件 :https://mp.weixin.qq.com/s/Mu-Xz4CLgdxJhcMJ7aKAHg
JVM 源码解读之 CMS 何时会进行 Full GC :https://mp.weixin.qq.com/s/zn3-9e7ZZ7skLo1XDL0xww
- 原因一:系统承载高并发请求,或者处理数据量过大,导致Young GC很贫乏,而且每次Young GC过后存活对象太多,内存分配不合理,Survivor区过小,导致对象频繁进入老年代,频繁触发Full GC。
- 原因二:系统一次性加载过多数据进内存,搞出来很多大对象,导致频繁有大对象进入老年带,必然频繁触发Full GC。
- 原因三:系统发生了内存泄漏,莫名其妙创建大量的对象,始终无法回收,一直占用在老年代里,必然频繁触发Full GC。
- 原因四:Metaspace(永久代)因为加载类过多触发Full GC。
- 原因五:误调用System.gc()触发Full GC。
解决方法:
- 原因一的解决方法是合理分配内存,调大Survivor区;
- 原因二、三,dump出内存快照,用MAT工具进行分析;
- 上述原因都不是,必然是第四、五种原因。
- 频繁Full GC的几种常见原因:https://blog.csdn.net/QQsilhonette/article/details/115607497
【待整理】
-Xss:设置每个线程的栈大小(默认1M)
-Xms: JVM初始分配的堆内存大小
-Xmx: JVM允许分配堆内存大小上限
-XX:newSize:表示新生代初始内存的大小,应该小于-Xms的值;
-XX:MaxnewSize:表示新生代可被分配的内存的最大上限
-Xmn:年轻代大小(是-XX:newSize、-XX:MaxnewSize两个参数的同时配置,JDK1.4版本以后才使用)
-XX:NewRatio 年轻代和老年代相对的比值大小大小 (默认2,若是4表示新生代:老年代=1:4)
-XX:SurvivorRatio=8 (8表示S0:eden=1:8,但是Survivor有from和to2个区域,所以S0+S1:eden=2:8)
-XX:PermSize:表示非堆区初始内存分配大小,永久代初始大小(JDK7之后废弃)
-XX:MaxPermSize:表示对非堆区分配的内存的最大上限,永久代最大大小(JDK7之后废弃)
‐XX:MetaspaceSize:表示metaspace首次使用不够而触发FGC的阈值,只对触发起作用,触发后会FGC以及扩容。默认20M左右(JDK7之后启用)
‐XX:MaxMetaspaceSize=256M:设置metaspace区域的最大值,扩容超过该值则OOM(JDK7之后启用)
-XX:TLABWasteTargetPercent:设置TLAB空间所占用Eden空间的百分比大小,默认是1%
-XX:PretrnureSizeThreshold:设置大对象的值,超过这个值大对象直接进入老年代
-XX:TenuringThreshold:设置对象晋升到老年代的最大分代年龄(默认15)
-XX:+DoEscapeAnalysis:开启逃逸分析
-XX:+HeapDumpOnOutOfMemoryError:如果发生OOM,导出堆dump
-XX:HeapDumpPath=/tmp/heapdump_$RANDOM.hprof
【收集器设置】
-XX:+UseSerialGC :设置串行收集器
-XX:+UseParNewGC :设置并发串行收集器(串行收集器多线程化|新生代?)
-XX:+UseParallelGC :设置并行收集器
-XX:+UseParalledlOldGC :设置并行年老代收集器
-XX:+UseConcMarkSweepGC :设置并发收集器(老年代?)
-XX:+UseCMSCompactAtFullCollection :
设置在FULL GC的时候, 对年老代的压缩;CMS是不会移动内存的,因此,这个非常容易产生碎片,导致内存不够用,因此,内存的压缩这个时候就会被启用。增加这个参数是个好习惯。可能会影响性能,但是可以消除碎片
-XX:CMSInitiatingOccupancyFraction=80:当老年代的内存占用率达到80%时会进行FGC。
预留足够的空间给young gc,防止从young gc 过来一个较大的内存块,而年老代无足够预留空间,无法提供内存快用于回收后的分配,引起强制的full gc,造成较长时间的线程中断
-XX:CMSFullGCsBeforeCompaction=1:
设置多少次full gc后进行内存压缩,由于并发收集器不对内存空间进行压缩,整理,所以运行一段时间以后会产生"碎片",使得运行效率降低.此值设置运行多少次GC以后对内存空间进行压缩,整理。
-XX:ParallelGCThreads=5
-XX:-+DisableExplicitGC 禁止系统GC
-XX:+PrintGC 输出GC日志
-XX:+PrintGCDetails 输出GC的详细日志
-XX:+PrintGCTimeStamps 输出GC的时间戳(以基准时间的形式)
-XX:+PrintGCDateStamps 输出GC的时间戳(以日期的形式)
-XX:+PrintHeapAtGC 在进行GC的前后打印出堆的信息
-XX:+PrintGCCause
-Xloggc:../logs/gc-%t.log 日志文件的输出路径(%t 代表时间)
-XX:+UseGCLogFileRotation
-XX:NumberOfGCLogFiles=10
-XX:GCLogFileSize=100M
java -verbose:class -version 可以查看刚开始加载的类
===========
java -XX:+PrintFlagsInitial 表示打印出所有参数选项以及默认值
java -XX:+PrintFlagsFinal 表示打印出所有参数选项在运行程序时生效的值
【参考配置参数】
java -Djava.library.path=/opt/file/jar
-noverify -Xms1G -Xmx2G
-server
-XX:+UseG1GC
-XX:MaxGCPauseMillis=30
-XX:InitiatingHeapOccupancyPercent=45
-XX:+ExplicitGCInvokesConcurrent
-XX:MaxInlineLevel=15
-verbose:gc
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-XX:+PrintGCTimeStamps
-XX:+UseGCLogFileRotation
-XX:NumberOfGCLogFiles=2
-XX:GCLogFileSize=10M
-Djava.io.tmpdir=/opt/java_io/tmpdir
-Xloggc:/opt/gc.log
-XX:OnOutOfMemoryError='sh /opt/oom_record.sh'
-Dlogback.configurationFile=/opt/file/logback.xml
-jar /FileTest.jar
JVM命令篇
一、获取堆实际使用信息
jmap -heap