0、序
1、参数设置
所有配置参数笔者默认为大小写敏感,在使用时一定校验是否有符号、拼写、大小写错误
1.1 参数分类
-
标准参数(-):所有的JVM实现都必须实现这些参数的功能,而且向上兼容;
-
非标准参数(-X):默认jvm实现这些参数的功能,但是并不保证所有jvm实现都满足,且不保证向上兼容;
-
非Stable参数(-XX):此类参数各个jvm实现会有所不同,将来可能会随时取消,需要慎重使用(但是,这些参数往往是非常有用的);
1.2 标准参数
在控制台输入java 获取支持的标准参数
1.2.1 -client
设置jvm使用client模式,启动速度快,但运行时性能和内存管理效率不高,通常用于客户端应用程序或者PC应用开发和调试。
1.2.2 -server
设置jvm使server模式,启动速度比较慢,运行时性能和内存管理效率很高,适用于生产环境。在具有64位能力的jdk环境下将默认启用该模式。
1.2.3 -verbose
-
-verbose:class 输出jvm载入类的相关信息,当jvm报告说找不到类或者类冲突时可此进 行诊断。
-
-verbose:gc 输出每次GC的相关情况,后面会有更详细的介绍。
-
-verbose:jni 输出native方法调用的相关情况,一般用于诊断jni调用错误信息。
1.2.4 -D<名称>=<值>
设置系统属性运行在此jvm之上的应用程序可用System.getProperty("property")得到value的值。如果value中有空格,则需要用双引号将该值括起来。 如:-Dname="space string" 该参数通常用于设置系统级全局变量值,如配置文件路径,以便该属性在程序中任何地方都可访问。
1.2.5 -X
在控制台输入,输出非标准的参数列表及其描述。
java -X
1.3 非标准参数
非标准参数,是在标准参数的基础上进行扩展的参数,不同类型JVM上参数也有所不同。图仅作示例,全部非标准参数内容请自行查阅。
1.3.1 -Xmx
JVM最大允许分配的堆内存;默认为物理内存的1/4或者1G,最小为2M;可以指定单位,比如k、m,若不指定,则默认为字节。
-Xmx1024m // == -Xmx1g,最大堆内存为1g
1.3.2 -Xms
JVM初始分配的堆内存,默认为物理内存的1/64,最小为1M;单位与-Xms一致,一般和Xmx配置成一样以避免每次gc后JVM重新分配内存;
1.3.3 -Xmn
年轻代内存大小(Eden+S0+S1)
1.3.4 -Xss
设置每个线程的栈大小,一般为512k/1M;
1.3.5 -Xloggc:file
与-verbose:gc功能类似,只是将每次GC事件的相关情况记录到一个文件中,文件的位置最好在本地,以避免网络的潜在问题。若与verbose命令同时出现,以-Xloggc为准。
-Xloggc:$CATALINA_BASE/logs/gc.log
1.4 非Stable参数
以-XX作为前缀的非Stable参数列表在JVM中可能是不健壮的,后续可能会在没有通知的情况下就直接取消了,但这些参数中的确有很多是对我们很有用的。
使用如下命令可以将支持的非Stable参数导出至文本:
java -XX:+PrintFlagsFinal > -XXCommandText.txt
在Hotspot中主要的参数可以大致分为3类:
-
性能参数( Performance Options):用于JVM的性能调优和内存分配控制,如初始化内存大小的设置;
-
行为参数(Behavioral Options):用于改变JVM的基础行为,如GC的方式和算法的选择;
-
调试参数(Debugging Options):用于监控、打印、输出等jvm参数,用于显示jvm更加详细的信息;
使用方法有4种:
-
-XX: + <option> 启用选项
-
-XX: - <option> 不启用选项
-
-XX:<option>=<number> 给选项设置一个数字类型值,可跟单位
如:-XX:NewSize=512M
-
-XX:<option>=<string> 给选项设置一个字符串值
如:-XX:HeapDumpPath=./dump.core
1.4.1 性能参数
-
-XX:NewRatio=4:设置年轻代与年老代的比值为4,则年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5,常用值为[2](默认值)、3、4
-
-XX:SurvivorRatio=4:设置年轻代中Eden区与Survivor区的比值为4,则S0+S1:Eden 的比值为1+1 : 4,一个Survivor区占整个年轻代的1/6,常用值4、[8]
-
-XX:MetaspaceSize=256m、-XX:MaxMetaspaceSize=256M :设置元空间默认大小、最大值(jdk1.7方法区、持久代 -XX:MaxPermSize=16M)
-
-XX:MaxTenuringThreshold= 0:设置分代年龄,默认为15,如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。
-
-XX:ParallelGCThreads=8:并发垃圾收集时开启线程数量
-
-XX:ConcGCThreads=0:并行垃圾收集时开启的线程数量
1.4.2 行为参数
-
-XX:-DisableExplicitGC:禁止调用System.gc();但jvm的gc仍然有效
-
-XX:+ScavengeBeforeFullGC:Minor GC优先于Full GC执行
-
-XX:+UseConcMarkSweepGC :ParNewGC + CMS GC
若出现Concurrent Mode Failure则使用 SerialOld GC替换CMS
-
-XX:+CMSParallelRemarkEnabled:搭配CMS使用,降低标记停顿
-
-XX:+UseSerialGC:Client模式下默认组合
SerialGC + SerialOld GC 组合
-
-XX:+UseParNewGC:ParNewGC + SerialOld GC 组合
-
-XX:+UseParallelGC:Server模式下默认组合
Parallel Scavenge GC + SerialOld GC 组合
-
-XX:+UseParallelOldGC:Parallel Scavenge GC + ParallelOldGC 组合
-
-XX:LargePageSizeInBytes=128M:内存页的大小
参考文献:《深入理解JAVA虚拟机》
1.4.3 调试参数
以下命令须配合-verbose:gc一起使用
-
-XX:+PrintGCDetails:打印GC详情
-
-XX:+PrintGCTimeStamps:打印发生fullgc的时间戳
-
-XX:-HeapDumpOnOutOfMemoryError:当首次遭遇OOM时导出此时堆中相关信息
-
-XX:+PrintGCApplicationStoppedTime:打印GC时SWT的时间
-
-XX:PrintHeapAtGC: 打印GC前后详细的堆栈信息
2、收集器套餐推荐
-
一般来说,Java桌面应用,建议采用-client模式套餐即Serial+Serial Old收集器组合:-XX:+UseSerialGC
-
在开发/测试环境,可以采用-server下默认参数即
Parallel Scavenge + Serial Old收集器组合:-XX:+UseParallelGC
-
在线上运算优先的环境,建议采用Parallel Scavenge+Serial Old收集器组合:-XX:+UseParallelGC
-
在线上服务响应优先的环境,建议采用ParNew+CMS+Serial Old收集器组合:-XX:+UseConcMarkSweepGC
3、内存分配
-
堆大小设置Xms 和 Xmx设置为老年代存活对象所占内存的3-4倍,即FullGC之后的老年代内存占用的3-4倍
-
永久代 PermSize和MaxPermSize元空间Metaspacesize及MaxMetaspacesize设置为老年代存活对象的1.2-1.5倍。 -
年轻代Xmn的设置为老年代存活对象的1-1.5倍。
-
老年代的内存大小设置为老年代存活对象的2-3倍。
如:当系统稳定运行一段时间后,老年代所占内存为64M则有如下性能参数设置:
-Xms256M -Xmx256M -Xmn86M -XX:MetaspaceSize=96M -XX:MaxMetaspaceSize=96M //年轻代:老年代 = 1:2
4、监控工具
4.1 命令行工具
4.1.1 jps命令
jps命令用于查询正在运行的JVM进程,命令格式为:
jps [option] [hostid]
常用的参数为:
-
-q:只输出VM ID,省略主类的名称
-
-m:输出虚拟机进程启动时传给主类main()函数的参数
-
-l:输出主类的全类名,如果进程执行的是Jar包,输出Jar路径
-
-v:输出虚拟机进程启动时JVM参数
4.1.2 jstat命令
jstat(Java Virtual Machine statistics monitoring tool)JDK自带的一个轻量级工具, 利用JVM内建的指令对Java应用程序的资源和性能进行实时的命令行的监控,包括了对Heap size和垃圾回收状况的监控。
jstat有如下选项:
-
-class:监视类装载、卸载数量、总空间及类装载所耗费的时间
-
-gc:监听Java堆状况,包括Eden区、两个Survivor区、老年代、永久代等的容量,以用空间、GC时间合计等信息
-
-gccapacity:监视内容与-gc基本相同,但输出主要关注java堆各个区域使用到的最大和最小空间
-
-gcutil:监视内容与-gc基本相同,但输出主要关注已使用空间占总空间的百分比
-
-gccause:与-gcutil功能一样,但是会额外输出导致上一次GC产生的原因
-
-gcnew:监视新生代GC状况
-
-gcnewcapacity:监视内同与-gcnew基本相同,输出主要关注使用到的最大和最小空间
-
-gcold:监视老年代GC情况
-
-gcoldcapacity:监视内同与-gcold基本相同,输出主要关注使用到的最大和最小空间
-
-gcpermcapacity:输出永久代使用到最大和最小空间
-
-compiler:输出JIT编译器编译过的方法、耗时等信息
-
-printcompilation:输出已经被JIT编译的方法
示例:
监控GC情况,被监控VMID为12636,每1000ms收集一次GC状态,共收集5次
-
S0C:S0区容量(S1区相同,略)
-
S0U:S0区已使用
-
EC:E区容量
-
EU:E区已使用
-
OC:老年代容量
-
OU:老年代已使用
-
MC:MetaSpace容量
-
MU:MetaSpace区已使用
-
CCSC:当前压缩类空间大小
-
CCSU:当前压缩类空间已使用大小
-
YGC:Young GC(Minor GC)次数
-
YGCT:Young GC总耗时
-
FGC:Full GC次数
-
FGCT:Full GC总耗时
-
GCT:GC总耗时
4.2 图形化工具
4.2.1 JVisualVM
VisualVM是一个集成多个JDK命令行工具的可视化工具,它具备了插件扩展功能的特性,通过插件的扩展,可用于显示虚拟机进程及进程的配置和环境信息(jps,jinfo),监视应用程序的CPU、GC、堆、方法区及线程的信息(jstat、jstack)等。
-
使用方法:控制台键入 jvisualvm打开工具
-
插件安装:下载对应jdk版本的visual gc插件,点工具-插件-已下载-打开安装。
-
启用监控:右键点击本地VM进程-打开-Visual GC 观察JVM内存运行情况
5、调优论述
5.1 目的
-
将转移到老年代的对象数量降低到最小;
-
减少full GC的执行时间 — 减少业务阻塞;
5.2 原则
-
多数的Java应用不需要在服务器上进行GC优化;
-
多数导致GC问题的Java应用,都不是因为我们参数设置错误,而是代码问题;
-
在应用上线之前,先考虑将机器的JVM参数设置到最优(最适合);
-
减少创建对象的数量;
-
减少使用全局变量和大对象;
-
GC优化是到最后不得已才采用的手段;
-
在实际使用中,分析GC情况优化代码比优化GC参数要多得多;
5.3 调优方法
-
方法1:稳定运行系统一段时间,使用监控工具查看当前JVM内存性能及gc情况,按照老年代占用内存比例,调整各内存性能参数。适合并发低、业务稳定应用。
-
方法2:分析估算单业务线完整生命周期占用的内存(主要是新生代)情况,并结合当前服务器可以稳定处理的峰值并发量,合理分配新生代内存容量及配比。适合业务处理时间短,高并发的应用。
-
方法3:选择适合的垃圾收集器套餐,系统默认参数足够应对绝大多数应用场景。
5.4 示例
仅供参考,先测后用
-Xmx300m //最大堆大小 -Xms300m //最小堆大小 -Xmn100m //新生代大小 -XX:SurvivorRatio=8 //Eden:Survivor -XX:+UseConcMarkSweepGC //使用ParNew+CMS+Serial Old收集器组合 -XX:MaxTenuringThreshold=15 //分代年龄,15岁以后进入老年代 -XX:ParallelGCThreads=8 //CMS并行线程数 -XX:ConcGCThreads=8 //ParNew并发线程数 -XX:+DisableExplicitGC //禁用System.gc() -XX:+HeapDumpOnOutOfMemoryError //导出堆OOM的异常信息 -XX:HeapDumpPath=d:/a.dump //导出路径 -XX:+PrintGCDetails //打印GC详情 -XX:+PrintGCTimeStamps //打印时间戳 -XX:+PrintHeapAtGC //打印GC前后堆的情况 -XX:+TraceClassLoading //显示类加载信息
Surprise