目录

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、除了能唤起并行垃圾回收器,还能卸载类。

五、调优参考

  1. 垃圾收集器跟内存大小的大致关系(不精确,需要根据实际环境测试)

    • Serial —> 几十兆

    • PS —> 上百兆 ~ 4G

    • CMS —> 4G ~ 10G

    • G1 —> 10G~上百G

    • ZGC —> 4T-16T(JDK13)

  2. 摘自互联网:某微服务项目单机并发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 jconsole jvisualvm GCeasy mat jmc JProfiler

← 返回技术