jvm-04-参数配置

Reference

参数说明

  • jvm参数分为:标准参数(以-开始)与非标准参数;

    可以通过java -help查看所有标准参数

  • 非标准参数又分两种

    • 不太标准(以-X开始),特定JVM厂商的参数。java -X可以打印出当前JVM版本所有非标准参数

      $ java -X
          -Xmixed           混合模式执行 (默认)
          -Xint             仅解释模式执行
          -Xbootclasspath:<用 : 分隔的目录和 zip/jar 文件>
                          设置搜索路径以引导类和资源
          -Xbootclasspath/a:<用 : 分隔的目录和 zip/jar 文件>
                          附加在引导类路径末尾
          -Xbootclasspath/p:<用 : 分隔的目录和 zip/jar 文件>
                          置于引导类路径之前
          -Xdiag            显示附加诊断消息
          -Xnoclassgc       禁用类垃圾收集
          -Xincgc           启用增量垃圾收集
          -Xloggc:<file>    将 GC 状态记录在文件中 (带时间戳)
          -Xbatch           禁用后台编译
          -Xms<size>        设置初始 Java 堆大小
          -Xmx<size>        设置最大 Java 堆大小
          -Xss<size>        设置 Java 线程堆栈大小
          -Xprof            输出 cpu 配置文件数据
          -Xfuture          启用最严格的检查, 预期将来的默认值
          -Xrs              减少 Java/VM 对操作系统信号的使用 (请参阅文档)
          -Xcheck:jni       对 JNI 函数执行其他检查
          -Xshare:off       不尝试使用共享类数据
          -Xshare:auto      在可能的情况下使用共享类数据 (默认)
          -Xshare:on        要求使用共享类数据, 否则将失败。
          -XshowSettings    显示所有设置并继续
          -XshowSettings:all
                          显示所有设置并继续
          -XshowSettings:vm 显示所有与 vm 相关的设置并继续
          -XshowSettings:properties
                          显示所有属性设置并继续
          -XshowSettings:locale
                          显示所有与区域设置相关的设置并继续
      
      -X 选项是非标准选项, 如有更改, 恕不另行通知。
      
      
      以下选项为 Mac OS X 特定的选项:
          -XstartOnFirstThread
                          在第一个 (AppKit) 线程上运行 main() 方法
          -Xdock:name=<应用程序名称>"
                          覆盖停靠栏中显示的默认应用程序名称
          -Xdock:icon=<图标文件的路径>
                          覆盖停靠栏中显示的默认图标
      
    • 特别不标准(以-XX开始),不同版本可能会废弃

      • java -XX:+PrintFlagsInitial可以查看参数默认值(所有参数太多,可以grep过滤下)

        $ java -XX:+PrintFlagsInitial
        [Global flags]
        intx ActiveProcessorCount                      = -1                                  {product}
        uintx AdaptiveSizeDecrementScaleFactor          = 4                                   {product}
        uintx AdaptiveSizeMajorGCDecayTimeScale         = 10                                  {product}
        uintx AdaptiveSizePausePolicy                   = 0                                   {product}
        uintx AdaptiveSizePolicyCollectionCostMargin    = 50                                  {product}
        uintx AdaptiveSizePolicyInitializingSteps       = 20                                  {product}
        uintx AdaptiveSizePolicyOutputInterval          = 0                                   {product}
        uintx AdaptiveSizePolicyWeight                  = 10                                  {product}
        uintx AdaptiveSizeThroughPutPolicy              = 0                                   {product}
        uintx AdaptiveTimeWeight                        = 25                                  {product}
        bool AdjustConcurrency                         = false                               {product}
        bool AggressiveHeap                            = false                               {product}
        bool AggressiveOpts                            = false                               {product}
        intx AliasLevel                                = 3                                   {C2 product}
        bool AlignVector                               = true                                {C2 product}
        intx AllocateInstancePrefetchLines             = 1                                   {product}
        intx AllocatePrefetchDistance                  = -1                                  {product}
        intx AllocatePrefetchInstr                     = 0                                   {product}
        intx AllocatePrefetchLines                     = 3                                   {product}
        intx AllocatePrefetchStepSize                  = 16                                  {product}
        intx AllocatePrefetchStyle                     = 1                                   {product}
        bool AllowJNIEnvProxy                          = false                               {product}
        bool AllowNonVirtualCalls                      = false                               {product}
                    
        ...
        
      • java -XX:+PrintFlagsFinal -version(-version也可以是其他可执行class),可以用来测试我们的参数组合最终的值是什么,启动会不会报错等

        $ java -XX:+UseParallelOldGC -XX:+PrintFlagsFinal -version | grep UseParallel
        bool UseParallelGC                             = true                                {product}
        bool UseParallelOldGC                         := true                                {product}
                
                
        $ java -XX:+UseG1GC -XX:+PrintFlagsFinal -version | grep G1GC
        bool UseG1GC                                  := true                                {product}
        
  • XX参数:

    • 布尔类型的参数,有”+”或”-“。例如,-XX:+用于激活选项,而-XX:-用于注销选项
    • 非布尔值的参数,如string或者integer,我们先写参数的名称,后面加上”=”,最后赋值。例如, -XX:=给赋值

推荐配置

可以通过https://opts.console.perfma.com/,生成推荐配置

JDK8 G1GC示例

-server -Xmx6g -Xms6g -XX:MaxMetaspaceSize=512M -XX:MetaspaceSize=512M 
-XX:+UseG1GC -XX:MaxGCPauseMillis=100 -XX:+ParallelRefProcEnabled
-XX:ErrorFile=logs/hs_err_pid%p.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=logs -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=3 -XX:GCLogFileSize=10M
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintCommandLineFlags -XX:+PrintGCApplicationStoppedTime -XX:+PrintHeapAtGC

查看进程启动参数

通过下面命令可以查看当前启动java进程的jvm启动参数

jcmd $pid VM.flags 
jmap -heap $pid 
jinfo -flags $pid
jps -v

配置说明

系统参数

系统参数以-D指定,通过System.getProperty读取

-Djava.security.egd=file:/dev/./urandom
-Djava.net.preferIPv4Stack=true
-Djava.awt.headless=true
-Dspring.profiles.active=dev

堆内存参数

  • -Xms4g: 堆(Heap)的初始化大小
  • -Xmx4g: 堆(Heap)的最大值

    Xms和Xmx设置一样,可以减轻伸缩堆大小带来的压力

  • -Xmn2g: 新生代的大小,等价参数-XX:MaxNewSize=2g -XX:NewSize=2g

    G1 GC下建议不设置该参数

  • -Xss512K: 每个线程的堆栈大小,默认值1m

    一般来说256就足够了

  • -XX:PermSize=256m: 永久代初始化大小

  • -XX:MaxPermSize=256m: 永久代最大内存大小

    到达后会触发FullGC,有时候我们会发现老生代使用很少,但是不断在做Full GC,可能就是Perm满了导致的

  • -XX:InitialBootClassLoaderMetaspaceSize=128m: 64位下默认4M,32位下默认2200K

    这个参数决定了NoKlass Metaspace的第一个内存Block的大小,即2*InitialBootClassLoaderMetaspaceSize

  • -XX:MaxMetaspaceSize=2g: 元数据区大小,默认是无穷大(int最大值)

    最好设置这个参数,否则可能导致metaspace无限制增加

  • -XX:NewRatio: 老年代/新生代的比例,默认值是2,即:老年代是新生代的2倍

  • -XX:SurvivorRatio: Eden区和Survivor(from/to)的比例,默认值是8,即:8:1:1(Eden:from:to)

  • -XX:+UseAdaptiveSizePolicy: 是否开启动态调整堆中各区的大小,jdk1.8默认开启

    并且最好不要关闭这个选项,除非对各区划分有明确规划 | -XX:+UseAdaptiveSizePolicy(开启),-XX:-UseAdaptiveSizePolicy(关闭)

堆外内存参数

  • -XX:MaxDirectMemorySize=1g: 堆外内存最大值,默认为Heap区总内存减去一个Survivor区的大小

    使用ByteBuffer.allocateDirect()得到一个DirectByteBuffer对象,如果已经超限,会主动执行Sytem.gc(),期待能主动回收一点堆外内存。然后休眠一百毫秒,如果totalCapacity没有降下来,且内存还是不足,就抛出OOM

GC配置参数

  • -XX:MaxTenuringThreshold: 新生代晋升老年代阈值(Monor GC后没有被回收的次数),CMS中默认值为6,G1中默认值为15
  • -XX:ParallelGCThreads=4: GC并发收集线程数,默认值2(linux)

    社区讨论https://club.perfma.com/topic/ParallelGCThreads

  • -XX:MaxGCPauseMillis=200: GC最大停顿时间,只对G1和Parallel Scavenge收集器有效

  • -XX:GCTimeRatio=99: 垃圾回收时间与程序运行时间的百分比,公式:1/(1+n),默认值99

  • -XX:+DisableExplicitGC: 是否禁用system.gc()

    System GC是保护机制(如堆外内存满时清理它的堆内引用对象),禁了system.gc() 未必是好事,只要没用什么特别烂的类库,真有人调了总有调的原因。

  • -XX:+PrintTenuringDistribution: 打印YGC各个年龄段的对象分布

JVM监控参数

  • -Xloggc | GC日志文件的输出路径

    jvm启动前路径必须存在

  • -XX:+PrintGC: 输出GC日志

  • verbose:gc: 与-XX:+PrintGC等价

  • -XX:+PrintGCDetails: 输出GC详细日志

  • -XX:+PrintGCTimeStamps: 输出GC时间戳

    格式:289.556,表示从jvm启动到发生垃圾回收所经历的的时间

  • -XX:+PrintGCDateStamps: 输出GC发生时间

    格式:2018-07-28T21:30:50.234+0800

  • -XX:+PrintGCApplicationStoppedTime: 打印完整的GC停顿时间

    例如:2019-09-20T09:30:00.204+0800: 33729.026: Total time for which application threads were stopped: 0.0059280 seconds, Stopping threads took: 0.0001000 seconds

  • -XX:+PrintHeapAtGC: 在进行GC的前后打印出堆信息

  • -XX:+PrintCommandLineFlags: 让JVM打印出那些已经被用户或者JVM设置过的详细的XX参数的名称和值,还会打印出以及因为这些参数隐式影响的参数。默认关闭

  • -XX:+PrintGCCause: 打印产生GC的原因,JDK8默认打开,JDK7要显式打开

  • -XX:ErrorFile: JVM crash时,hotspot 会生成一个error文件,提供JVM状态信息的细节

    -XX:ErrorFile=${LOGDIR}/jvmerr_%p.log,输出到指定的路径方便查找

  • -XX:+HeapDumpOnOutOfMemoryError: 在OOM,JVM快死掉的时候,输出Heap Dump到指定文件

    两个参数要配合使用 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=${LOGDIR}/,路径只指向目录,JVM会保持文件名的唯一性,叫java_pid${pid}.hprof。因为如果指向文件,而文件已存在,反而不能写入。在容器环境下,输出4G的HeapDump,在普通硬盘上会造成20秒以上的硬盘IO跑满,影响到同一宿主机上所有其他的容器