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 |
- Author:mcbilla
- URL:http://mcbilla.com/article/10e85c7d-7c1d-80c0-860f-e5e0ef459a17
- Copyright:All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!
Relate Posts