JVM 参数配置
# 参数说明
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=<图标文件的路径> 覆盖停靠栏中显示的默认图标
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43特别不标准(以-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} ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27- 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}
1
2
3
4
5
6
7
XX参数:
- 布尔类型的参数,有”+”或”-“。例如,-XX:+用于激活选项,而-XX:-用于注销选项
- 非布尔值的参数,如string或者integer,我们先写参数的名称,后面加上”=”,最后赋值。例如, -XX:=给赋值
# 推荐配置
可以通过https://opts.console.perfma.com/ (opens new window),生成推荐配置
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
2
3
4
# 查看进程启动参数
通过下面命令可以查看当前启动java进程的jvm启动参数
jcmd $pid VM.flags
jmap -heap $pid
jinfo -flags $pid
jps -v
2
3
4
# 配置说明
# 系统参数
系统参数以-D指定,通过System.getProperty读取
-Djava.security.egd=file:/dev/./urandom
-Djava.net.preferIPv4Stack=true
-Djava.awt.headless=true
-Dspring.profiles.active=dev
2
3
4
# 堆内存参数
-Xms4g: 堆(Heap)的初始化大小
-Xmx4g: 堆(Heap)的最大值
Xms和Xmx设置一样,可以减轻伸缩堆大小带来的压力
-Xmn2g: 新生代的大小,等价参数-XX:MaxNewSize=2g -XX:NewSize=2g
G1 GC下建议不设置该参数
-Xss512K: 每个线程的堆栈大小,默认值1m
一般来说256就足够了
-XX:PermSize=256m: 永久代初始化大小(1.8 之后使用元空间替代)
-XX:MaxPermSize=256m: 永久代最大内存大小(1.8 之后使用元空间替代)
到达后会触发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 (opens new window)
-XX:GCTimeRatio=99: 垃圾回收时间与程序运行时间的百分比,公式:1/(1+n),默认值99
-XX:+DisableExplicitGC: 是否禁用system.gc()
System GC是保护机制(如堆外内存满时清理它的堆内引用对象),禁了system.gc() 未必是好事,只要没用什么特别烂的类库,真有人调了总有调的原因。
-XX:+PrintTenuringDistribution: 打印YGC各个年龄段的对象分布
-XX:ConcGCThreads=n: 并发收集线程数,默认等于cpu核心数
# G1 配置参数
- ‐XX:+UseG1GC: 开启 G1 收集器
- ‐XX:G1HeapRegionSize: 每个 region 区域大小,必须是默认 = 总堆空间 / 2048
- -XX:MaxGCPauseMillis=200: GC 最大停顿时间,只对 G1 和 Parallel Scavenge 收集器有效
- -XX:InitiatingHeapOccupancyPercent: 老年代内存占用打到设置(默认45,即45%)比例时,进行混合回收(MixedGC)
- -XX:G1MixedGCLiveThresholdPercent=n: MixedGC 时,只有 存活对象低于这个比例才会被回收,默认 85(即 85%)
- -XX:G1OldCSetRegionThresholdPercent=n: Mixed GC 时,能选入 CSet 的最多 old region 数量,默认 10 (即 10%)
提示
G1MixedGCLiveThresholdPercent 和 G1OldCSetRegionThresholdPercent 两个参数必须配合参数-XX:+UnlockExperimentalVMOptions 使用,并且只能加在 UnlockExperimentalVMOptions 后才能生效
# 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跑满,影响到同一宿主机上所有其他的容器
Reference