type
status
date
slug
summary
tags
category
icon
password

1、概述

我们根据 JVM 参数以 -X 开头或 -XX 开头将 JVM 参数分成三类:
  • - 开头的是标准 VM 选项,VM 规范的选项
  • -X 开头的都是非标准的,这些参数并不能保证在所有的 JVM 上都被实现,而且如果在新版本有什么改动也不会发布通知。
  • -XX 开头的都是不稳定的并且不推荐在生产环境中使用,这些参数的改动也不会发布通知。
根据 JVM 参数后面跟的参数值类型,可以分为:
  • 数字类型参数,通过 -XX:=设定。数字可以是 m/M(兆字节), k/K(千字节), g/G(G字节)。比如 -XX:MaxPermSize=64m
  • Bool 类型参数,-XX:+表示打开, -XX:- 表示关闭。比如 -XX:+PrintGCDetails
  • String 类型参数,通过 -XX:= 设定,通常用来指定一个文件、路径、或者命令列表。比如 -XX:HeapDumpPath=/tmp/heap-dump.hprof
执行 java -help 可以列出 Java 程序启动时支持的标准选项,不同的 JVM 实现是不同的。常见的标准选项有:
  • -D<name>=<value>:设置系统变量。
  • -ea:ea(enable assertion)表示开启断言功能。Java 默认是禁止断言的,如果不开启断言功能,断言语句可能不会执行。建议只在开发测试环境中使用断言进行单元测试,例如使用 Idea 创建的 Junit 单元测试会自动加上这个参数。
执行 java -X 可以列出 Java 程序启动时支持的不标准参数。常用的不标准选项有:
  • -Xms<size>:初始堆大小。
  • -Xmx<size>:最大堆大小。
  • -Xloggc:<file>:把 GC 日志信息记录到文件。

2、最重要的JVM参数

下面这些是生产实战中最常用的 JVM 参数,必须要掌握。

2.1 堆内存和元空间相关

注意:
  • 一般生产环境将 -Xms-Xmx 设置为相同的值。原因是如果两个值不相同,JVM 会进行内存的动态扩缩容:默认空余堆内存小于40%时,JVM就会增大堆直到 -Xmx 的最大限制;空余堆内存大于 70% 时,JVM会减少堆直到 -Xms 的最小限制。每次扩缩容都会产生 Full GC,导致应用停顿。所以把 -Xms-Xmx 设置为相同的值可以避免这种动态扩容产生的 Full GC 停顿。
  • Metaspace 的初始容量并不是 -XX:MetaspaceSize 设置,无论 -XX:MetaspaceSize 配置什么值,对于 64 位 JVM 来说,Metaspace 的初始容量都是 21807104(约 20.8m)。Metaspace 由于使用不断扩容到-XX:MetaspaceSize参数指定的量,就会发生 FGC,且之后每次 Metaspace 扩容都会发生 Full GC。也就是说,MetaspaceSize 表示 Metaspace 使用过程中触发 Full GC 的阈值,只对触发起作用。

2.2 垃圾回收器相关

启动垃圾回收器:
垃圾回收器优化常用参数:

2.3 GC 日志记录

2.4 处理OOM

3、JVM参数总览

3.1 基础参数

参数
默认值或限制
说明
-Xms
操作系统物理内存的1/64但小于1G
默认当空余堆内存大于70%时,JVM会减小heap的大小到-Xms指定的大小,可通过-XX:MaxHeapFreeRation=来指定这个比列。Server端JVM最好将-Xms和-Xmx设为相同值,避免每次垃圾回收完成后JVM重新分配内存
-Xmx
物理内存的1/4但小于1G
JVM可申请的最大Heap值,默认当空余堆内存小于40%时,JVM会增大Heap到-Xmx指定的大小,可通过-XX:MinHeapFreeRation=来指定这个比列。最佳设值应该视物理内存大小及计算机内其他内存开销而定
-Xmn
堆内存的四分之一
Java Heap Young区大小。整个堆大小=年轻代大小 + 年老代大小 (相对于HotSpot 类型的虚拟机来说,java 7 以后已经不存在持久代)。持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。
-Xss
JDK5以前每个线程堆栈大小为256K,JDK5以后每个线程堆栈大小为1M
Java每个线程的Stack大小。根据应用的线程所需内存大小进行调整。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。一般小的应用, 如果栈不是很深, 应该是128k够用的 大的应用建议使用256k。这个选项对性能影响比较大,需要严格的测试。(校长)和threadstacksize选项解释很类似,官方文档似乎没有解释,在论坛中有这样一句话:"-Xss is translated in a VM flag named ThreadStackSize”一般设置这个值就可以了。
-XX:NewSize
年轻代初始内存大小
-XX:MaxNewSize
年轻代最大内存大小
-XX:PermSize
物理内存的1/64
持久代(方法区)的初始内存大小。
-XX:MaxPermSize
持久代(方法区)的最大内存大小。
-XX:NewRatio=2
新生代和年老代的堆内存占用比例, 例如2表示新生代占年老代的1/2,占整个堆内存的1/3
-XX:SurvivorRatio=8
Eden与Survivor的占用比例。例如8表示,一个survivor区和Eden区的比例1:8。我们的新生代有2个survivor,即S0和S1,每个survivor区占1/10的新生代内存,所以survivor区总占用新生代内存的 2/10,Eden区占用新生代内存的8/10

3.2 功能开关

参数
默认值或限制
说明
-XX:-AllowUserSignalHandlers
限于Linux和Solaris,默认不启用
允许为java进程安装信号处理器,信号处理参见类:sun.misc.Signal, sun.misc.SignalHandler
-XX:+DisableExplicitGC
默认启用
禁止在运行期显式地调用System.gc()
-XX:+FailOverToOldVerifier
JDK 6 新引入选项,默认启用
如果新的Class校验器检查失败,则使用老的校验器(失败原因:因为JDK6最高向下兼容到JDK1.2,而JDK1.2的class info 与JDK6的info存在较大的差异,所以新校验器可能会出现校验失败的情况)
-XX:+HandlePromotionFailure
JDK 6 以前是默认不启用,JDK 6 默认启用
关闭新生代收集担保
-XX:+MaxFDLimit
限于Solaris,默认启用
设置java进程可用文件描述符为操作系统允许的最大值。
-XX:PreBlockSpin=10
-XX:+UseSpinning 必须先启用,对于JDK 6 来说已经默认启用了,这里默认自旋10次
控制多线程自旋锁优化的自旋次数
-XX:-RelaxAccessControlCheck
默认不启用
在Class校验器中,放松对访问控制的检查,作用与reflection里的setAccessible类似
-XX:+ScavengeBeforeFullGC
默认启用
在Full GC前触发一次Minor GC
-XX:+UseAltSigs
限于Solaris,默认启用
为了防止与其他发送信号的应用程序冲突,允许使用候补信号替代 SIGUSR1和SIGUSR2
-XX:+UseBoundThreads
限于Solaris, 默认启用
绑定所有的用户线程到内核线程, 减少线程进入饥饿状态(得不到任何cpu time)的次数
-XX:+UseGCOverheadLimit
默认启用
限制GC的运行时间。如果GC耗时过长,就抛OOM
-XX:+UseLWPSynchronization
限于solaris,默认启用
使用轻量级进程(内核线程)替换线程同步
-XX:-UseSpinning
java1.4.2和1.5需要手动启用, java6默认已启用
启用多线程自旋锁优化
-XX:+UseTLAB
1.4.2以前和使用-client选项时,默认不启用,其余版本默认启用
启用线程本地缓存区
-XX:+UseSplitVerifier
JDK 5 默认不启用,JDK 6 默认启用
使用新的Class类型校验器
-XX:+UseThreadPriorities
默认启用
使用本地线程的优先级
-XX:+UseVMInterruptibleIO
限于solaris,默认启用
在solaris中,允许运行时中断线程
-XX:+UseSerialGC
client端默认启用
使用 Serial + Serial Old 收集器,Client 模式下的默认值
-XX:+UseParNewGC
JDK 8 以上版本被废弃
使用 ParNew + Serial Old 搜集器
-XX:+UseConcMarkSweepGC
使用 ParNew + CMS/Serial Old 收集器,Serial Old 收集器将作为CMS收集器出现 Concurrent Mode Failure 失败后的后备收集器使用。
-XX:+UseParallelGC
server端默认启用
使用 Parallel Scavenge + Serial Old(PS MarkSweep) 收集器,Server 模式下的默认值
-XX:+UseParallelOldGC
使用 Parallel Scavenge + Parallel Old 收集器
-XX:+UseG1GC
JDK 8 以后才被引入
启用G1收集器,不分新生代和老年代
常用垃圾回收器设置如下
新生代
老年代
JVM参数
Serial
Serial Old
-XX:+UseSerialGC
Parallel Scavenge
Serial Old
-XX:+UseParallelGC
Parallel Scavenge
Parallel Old
-XX:+UseParallelGC -XX:+UseParallelOldGC
Parallel New
Serial Old
-XX:+UseParNewGC
Parallel New
CMS
-XX:+UseParNewGC -XX:+UseConcMarkSweepGC
G1
-XX:+UseG1GC

3.3 性能参数

参数
默认值或限制
说明
-XX:+AggressiveOpts
JDK 6 update 6后引入,但需要手动启用, JDK 6 默认启用
启用JVM开发团队最新的调优成果。例如编译优化,偏向锁,并行年老代收集等
-XX:CompileThreshold=10000
1000
通过JIT编译器,将方法编译成机器码的触发阀值,可以理解为调用方法的次数,例如调1000次,将方法编译为机器码
-XX:LargePageSizeInBytes=4m
默认4m,amd64位为2m
设置堆内存的内存页大小
-XX:MaxHeapFreeRatio=70
70
GC后,如果发现空闲堆内存占到整个预估上限值的70%,则收缩预估上限值
-XX:MinHeapFreeRatio=40
40
GC后,如果发现空闲堆内存占到整个预估上限值的40%,则增大上限值
-XX:ReservedCodeCacheSize=32m
Solaris 64-bit, amd64, -server x86: 48m, 1.5.0_06之前, Solaris 64-bit amd64: 1024m, 其他默认 32m
设置代码缓存的最大值,编译时用
-XX:TargetSurvivorRatio=50
50
实际使用的survivor空间大小占比。默认是50%,最高90%
-XX:ThreadStackSize=512
Sparc: 512, Solaris x86: 320 (5.0以前 256), Sparc 64 bit: 1024, Linux amd64: 1024 (5.0 以前 0), 其他默认 512.
线程堆栈大小
-XX:+UseBiasedLocking
JDK 5 update 6后引入,但需要手动启用,JDK6 默认启用
启用偏向锁
-XX:+UseFastAccessorMethods
默认启用
优化原始类型的getter方法性能(get/set:Primitive Type)
-XX:-UseISM
默认启用
启用solaris的ISM
-XX:+UseLargePages
JDK 5 update 5后引入,但需要手动启用, JDK6默认启用
启用大内存分页
-XX:+UseMPSS
1.4.1 之前: 不启用, 其余版本默认启用
启用solaris的MPSS,不能与ISM同时使用
-XX:+UseStringCache
默认开启
启用缓存常用的字符串。
-XX:AllocatePrefetchLines=1
1
Number of cache lines to load after the last object allocation using prefetch instructions generated in JIT compiled code. Default values are 1 if the last allocated object was an instance and 3 if it was an array.
-XX:AllocatePrefetchStyle=1
1
Generated code style for prefetch instructions.0 – no prefetch instructions are generate*d*,1 – execute prefetch instructions after each allocation,2 – use TLAB allocation watermark pointer to gate when prefetch instructions are executed.
-XX:+UseCompressedStrings
Java 6 update 21 有一选项
其中,对于不需要16位字符的字符串,可以使用byte[] 而非char[]。对于许多应用,这可以节省内存,但速度较慢(5%-10%)
-XX:+OptimizeStringConcat
JDK 6 update 20 中引入
优化字符串连接操作在可能的情况下

3.4 锁相关参数

参数
默认值或限制
说明
-XX:BiasedLockingBulkRebiasThreshold
20
偏向锁批量重偏向阈值
-XX:BiasedLockingBulkRevokeThreshold
40
偏向锁批量撤销阈值
-XX:+UseBiasedLocking
开启
使用偏向锁,jdk6之后默认开启
-XX:BiasedLockingStartupDelay
4
延迟偏向时间, 默认不为0,意思为jvm启动多少ms以后开启偏向锁机制(此处设为0,不延迟)

3.5 调试参数

参数
默认值或限制
说明
-XX:+PrintCommandLineFlags
打印出那些已经被用户或者JVM设置过的详细的XX参数的名称和值。换句话说,它列举出 -XX:+PrintFlagsFinal的结果中第三列有":="的参数。
-XX:+PrintFlagsFinal
查看自己设置的和jvm设置的所有参数,":="表示是用户自定义的值,”=“表示是默认的值
-XX:+PrintFlagsInitial
只查看jvm设置的默认参数
-XX:-CITime
打印发费在JIT编译上的时间
-XX:ErrorFile
JDK 6 中引入
错误文件
-XX:-ExtendedDTraceProbes
JDK 6 中引入仅在Solaris
启用性能的影响DTrace探测器
-XX:HeapDumpPath
1.4.2 update 12, 5.0 update 7
指定HeapDump的文件路径或目录
-XX:-HeapDumpOnOutOfMemoryError
1.4.2 update 12, 5.0 update 7
当抛出OOM时进行HeapDump
-XX:OnError
1.4.2 update 9
当发生错误时执行用户指定的命令
-XX:OnOutOfMemoryError
1.4.2 update 12, 6
当发生OOM时执行用户指定的命令
-XX:-PrintClassHistogram
1.4.2
当Ctrl+Break发生时打印Class实例信息,与jmap -histo相同
-XX:-PrintConcurrentLocks
6
当Ctrl+Break发生时打印java.util.concurrent的锁信息, 与jstack -l相同
-XX:-PrintCommandLineFlags
5
查看默认设置收集器类型
-XX:-PrintCompilation
当方法被编译时打印信息
-XX:-PrintGC
当GC发生时打印信息
-XX:-PrintGCDetails
1.4.0
打印GC详细信息
-XX:-PrintGCTimeStamps
1.4.0
打印GC时间,该时间从程序启动开始算起
-XX:+PrintGCDateStamps
1.4.0
打印GC时间戳,例如2020-04-16T20:59:08.092
-XX:-PrintTenuringDistribution
打印Tenuring年龄信息
-XX:-TraceClassLoading
跟踪类加载
-XX:-TraceClassLoadingPreorder
1.4.2
跟踪所有加载的引用类
-XX:-TraceClassResolution
1.4.2
跟踪常量池的变化
-XX:-TraceClassUnloading
跟踪类的卸载
-XX:-TraceLoaderConstraints
6
Trace recording of loader constraints
-XX:+PerfSaveDataToFile
退出时保存jvmstat二进制文件
-XX:ParallelGCThreads
设置新生代与老年代并行垃圾回收器的线程数
-XX:+UseCompressedOops
Enables the use of compressed pointers (object references represented as 32 bit offsets instead of 64-bit pointers) for optimized 64-bit performance with Java heap sizes less than 32gb.
-XX:+AlwaysPreTouch
Pre-touch the Java heap during JVM initialization. Every page of the heap is thus demand-zeroed during initialization rather than incrementally during application execution.
-XX:AllocatePrefetchDistance
Sets the prefetch distance for object allocation. Memory about to be written with the value of new objects is prefetched into cache at this distance (in bytes) beyond the address of the last allocated object. Each Java thread has its own allocation point. The default value varies with the platform on which the JVM is running.
-XX:InlineSmallCode
当编译的代码小于指定的值时,内联编译的代码
-XX:MaxInlineSize
内联方法的最大字节数
-XX:FreqInlineSize
内联频繁执行的方法的最大字节码大小
-XX:LoopUnrollLimit
Unroll loop bodies with server compiler intermediate representation node count less than this value. The limit used by the server compiler is a function of this value, not the actual value. The default value varies with the platform on which the JVM is running.
-XX:InitialTenuringThreshold
设置初始的对象在新生代中最大存活次数
-XX:MaxTenuringThreshold
设置对象在新生代中最大的存活次数,最大值15,并行回收机制默认为15,CMS默认为4
线上问题排查常用命令JVM系列:SafePoint与Stop The World详解
mcbilla
mcbilla
一个普通的干饭人🍚
Announcement
type
status
date
slug
summary
tags
category
icon
password
🎉欢迎来到飙戈的博客🎉
-- 感谢您的支持 ---
👏欢迎学习交流👏