本文主要基于周志明老师的《深入理解Java虚拟机》。
JVM Tuning
JVM命令行参数
JVM的命令行参数参考:
https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html
HotSpot参数分类
标准参数
标准参数指所有的HotSpot都支持,以**-**开头。
非标准参数
非标准参数指特定版本HotSpot支持的参数,以**-X**开头。
不稳定参数
不稳定参数指下个版本HotSpot可能取消的参数,以**-XX**开头。
实用命令
查看支持的标准参数
java -h
查看支持的非标准参数
java -X
查看JVM默认参数值
java -XX:+PrintFlagsInitial -version
查看程序使用的默认JVM参数
java -XX:+PrintCommandLineFlags -version
查看JVM最终参数值
java -XX:+PrintFlagsFinal -version
实用日志参数设置
-Xloggc:/opt/xxx/logs/xxx-xxx-gc-%t.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=20M -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCCause
JVM自带工具
jps(JVM Process Status Tool)
如果同时启动了多个虚拟机进程,无法根据进程名词定位时,那就必须依赖jps命令显示主类的功能才能区分了。
- -l
- 输出主类的全名,如果进程执行的是JAR包,则输出JAR路径。
- -v
- 输出虚拟机进程启动时的JVM参数。
jinfo(Configuration Info for Java)
jinfo的作用是实时查看和调整虚拟机的各项参数。
输出全部参数和系统属性
jinfo <pid>
输出全部参数
jinfo -flags <pid>
输出全部系统属性
jinfo -sysprops <pid>
查看属性
查看某个java进程的name属性
jinfo -flag <name> <pid>
jinfo -flag UseG1GC 450308
-XX:-UseG1GC
修改属性
参数只有被标记为manageable的flags可以被实时修改
jinfo -flag [+|-] PID
jinfo -flag <name>=<value> PID
jstat(JVM Statistics Monitoring Tool)
jstat是JVM性能统计监控工具,可以查看虚拟机的性能统计信息。
jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]
查看当前版本支持的选项
jstat -options
选项 | 含义 |
---|---|
-class | 类加载情况 |
-compiler | JIT |
-gc | GC堆状况 |
-gccapacity | 各区大小 |
-gccause | 最近一次GC统计和愿意 |
-gcmetacapacity | 原空间大小 |
-gcnew | 年轻代统计 |
-gcnewcapacity | 年轻代大小 |
-gcold | 老年代统计 |
-gcoldcapacity | 老年代大小 |
-gcutil | GC统计汇总 |
-printcompilation | HotSpot编译统计 |
显示和gc相关的堆信息
jstat -gc <455128>
- S0C:第一个幸存区的大小(字节)
- S1C:第二个幸存区的大小(字节)
- S0U:第一个幸存区的使用大小(字节)
- S1U:第二个幸存区的使用大小(字节)
- EC:伊甸园区的大小(字节)
- EU:伊甸园区的使用大小(字节)
- OC:老年代大小(字节)
- OU:老年代使用大小(字节)
- MC:元空间大小(字节)
- MU:元空间使用大小(字节)
- CCSC:压缩类空间大小(字节)
- CCSU:压缩类空间使用大小(字节)
- YGC:年轻代垃圾回收次数
- YGCT:年轻代垃圾回收消耗时间(秒)
- FGC:老年代垃圾回收次数
- FGCT:老年代垃圾回收消耗时间(秒)
- GCT:垃圾回收消耗总时间(秒)
jstack(Stack Trace for Java)
jstack是java查看跟踪栈信息的工具,可用户排查死锁问题,重点关注:WAITING、BLOCKED状态的线程。
jstack pid
jmap(Memory Map for Java)
打印堆内存相关信息
jmap -heap <pid>
dump出堆内存相关信息
jmap -dump:format=b,file=heap.hprof <PID>
发生堆内存溢出的时自动dump
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=heap.hprof
jhat(JVM Heap Analysis Tool)
有时dump出来的堆很大,在启动时会报堆空间不足的错误,可加参数:jhat -J-Xmx512m 。这个内存大小可根据自己电脑进行设置。
jhat <heap dump file>
Arthas
Arthas 是Alibaba开源的Java诊断工具。
https://arthas.aliyun.com/zh-cn/
GC常用参数
- -Xmn -Xms -Xmx -Xss
年轻代 最小堆 最大堆 栈空间 - -XX:+UseTLAB
使用TLAB,默认打开 - -XX:+PrintTLAB
打印TLAB的使用情况 - -XX:TLABSize
设置TLAB大小 - -XX:+DisableExplictGC
System.gc()不管用 ,FGC - -XX:+PrintGC
- -XX:+PrintGCDetails
- -XX:+PrintHeapAtGC
- -XX:+PrintGCTimeStamps
- -XX:+PrintGCApplicationConcurrentTime (低)
打印应用程序时间 - -XX:+PrintGCApplicationStoppedTime (低)
打印暂停时长 - -XX:+PrintReferenceGC (重要性低)
记录回收了多少种不同引用类型的引用 - -verbose:class
类加载详细过程 - -XX:+PrintVMOptions
- -XX:+PrintFlagsFinal -XX:+PrintFlagsInitial
必须会用 - -Xloggc:opt/log/gc.log
- -XX:MaxTenuringThreshold
升代年龄,最大值15 - 锁自旋次数 -XX:PreBlockSpin 热点代码检测参数-XX:CompileThreshold 逃逸分析 标量替换 …
这些不建议设置
Parallel常用参数
- -XX:SurvivorRatio
- -XX:PreTenureSizeThreshold
大对象到底多大 - -XX:MaxTenuringThreshold
- -XX:+ParallelGCThreads
并行收集器的线程数,同样适用于CMS,一般设为和CPU核数相同 - -XX:+UseAdaptiveSizePolicy
自动选择各区大小比例
CMS常用参数
- -XX:+UseConcMarkSweepGC
- -XX:ParallelCMSThreads
CMS线程数量 - -XX:CMSInitiatingOccupancyFraction
使用多少比例的老年代后开始CMS收集,默认是68%(近似值),如果频繁发生SerialOld卡顿,应该调小,(频繁CMS回收) - -XX:+UseCMSCompactAtFullCollection
在FGC时进行压缩 - -XX:CMSFullGCsBeforeCompaction
多少次FGC之后进行压缩 - -XX:+CMSClassUnloadingEnabled
- -XX:CMSInitiatingPermOccupancyFraction
达到什么比例时进行Perm回收 - GCTimeRatio
设置GC时间占用程序运行时间的百分比 - -XX:MaxGCPauseMillis
停顿时间,是一个建议时间,GC会尝试用各种手段达到这个时间,比如减小年轻代
G1常用参数
- -XX:+UseG1GC
- -XX:MaxGCPauseMillis
建议值,G1会尝试调整Young区的块数来达到这个值 - -XX:GCPauseIntervalMillis
?GC的间隔时间 - -XX:+G1HeapRegionSize
分区大小,建议逐渐增大该值,1 2 4 8 16 32。
随着size增加,垃圾的存活时间更长,GC间隔更长,但每次GC的时间也会更长
ZGC做了改进(动态区块大小) - G1NewSizePercent
新生代最小比例,默认为5% - G1MaxNewSizePercent
新生代最大比例,默认为60% - GCTimeRatio
GC时间建议比例,G1会根据这个值调整堆空间 - ConcGCThreads
线程数量 - InitiatingHeapOccupancyPercent
启动G1的堆空间占用比例