JVM 启动参数大全
官方网站
- https://docs.oracle.com/javacomponents/jrockit-hotspot/migration-guide/cloptions.htm#JRHMG127
- https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html#BGBCIEFC
介绍
java启动参数共分为三类;
- 标准参数(-),所有的JVM实现都必须实现这些参数的功能,而且向后兼容;
- 非标准参数(-X),默认jvm实现这些参数的功能,但是并不保证所有jvm实现都满足,且不保证向后兼容;
- 非Stable参数(-XX),此类参数各个jvm实现会有所不同,将来可能会随时取消,需要慎重使用;
标准参数
标准参数是用过Java的人都最熟悉的,就是你在运行java命令时后面加上的参数,如 java -version, java -jar
等,输入命令 java -help
或 java -?
就能获得当前机器所有java的标准参数列表。
1 |
|
非标准参数(又称为扩展参数)
非标准参数,是在标准参数的基础上进行扩展的参数,输入“java -X
”命令,能够获得当前JVM支持的所有非标准参数列表。
在不同类型的JVM中,采用的参数有所不同
-Xint
设置jvm以解释模式运行,所有的字节码将被直接执行,而不会编译成本地码。
-Xcomp
它(-Xint)正好相反,JVM在第一次使用时会把所有的字节码编译成本地代码,从而带来最大程度的优化。
然而,很多应用在使用-Xcomp也会有一些性能损失,当然这比使用-Xint损失的少,原因是-xcomp没有让JVM启用JIT编译器的全部功能。JIT编译器可以对是否需要编译做判断,如果所有代码都进行编译的话,对于一些只执行一次的代码就没有意义了。
-Xmixed
混合模式,将解释模式与编译模式进行混合使用,由jvm自己决定,这是jvm默认的模式,也是推荐使用的模式。
-Xbatch
关闭后台代码编译,强制在前台编译,编译完成之后才能进行代码执行;默认情况下,jvm在后台进行编译,若没有编译完成,则前台运行代码时以解释模式运行。
-Xmn
新生代内存大小,包括E区和两个S区的总和,使用方法如:-Xmn65535,-Xmn1024k,-Xmn512m,-Xmn1g (-Xms,-Xmx也是种写法)
-Xms<size> 重要
指定jvm堆的初始大小,也是堆大小的最小值,默认值是总共的物理内存/64(且小于1G),最小为1M,可以指定单位,比如k、m,若不指定,则默认为字节。默认情况下,当堆中可用内存小于40%(这个值可以用-XX: MinHeapFreeRatio 调整,如-X:MinHeapFreeRatio=30)时,堆内存会开始增加,一直增加到-Xmx的大小;
-Xmx<size> 重要
指定jvm堆的最大值,默认值是总共的物理内存/4或者1G,最小为2M,如果Xms和Xmx都不设置,则两者大小会相同,默认情况下,当堆中可用内存大于70%(这个值可以用-XX: MaxHeapFreeRatio 调整,如-X:MaxHeapFreeRatio=60)时,堆内存会开始减少,一直减小到-Xms的大小;
整个堆的大小=年轻代大小+年老代大小,堆的大小不包含持久代大小,如果增大了年轻代,年老代相应就会减小,官方默认的配置为年老代大小/年轻代大小=2/1左右(使用-XX:NewRatio可以设置-XX:NewRatio=5,表示年老代/年轻代=5/1);
建议在开发测试环境可以用Xms和Xmx分别设置最小值最大值,但是在线上生产环境,Xms和Xmx设置的值必须一样,原因与年轻代一样——防止抖动;
-Xss<size>
这个参数用于设置每个线程的栈内存,默认1M
-Xbootclasspath:bootclasspath
让jvm从指定路径(可以是分号分隔的目录、jar、或者zip)中加载bootclass,用来替换jdk的rt.jar;若非必要,一般不会用到;
-Xbootclasspath/a:path
将指定路径的所有文件追加到默认bootstrap路径中;
-Xbootclasspath/p:path
让jvm优先于bootstrap默认路径加载指定路径的所有文件;
-Xcheck:jni
对JNI函数进行附加check;此时jvm将校验传递给JNI函数参数的合法性,在本地代码中遇到非法数据时,jmv将报一个致命错误而终止;使用该参数后将造成性能下降,请慎用。
-Xfuture
让jvm对类文件执行严格的格式检查(默认jvm不进行严格格式检查),以符合类文件格式规范,推荐开发人员使用该参数。
-Xnoclassgc
关闭针对class的gc功能;因为其阻止内存回收,所以可能会导致OutOfMemoryError错误,慎用;
-Xincgc
开启增量gc(默认为关闭);这有助于减少长时间GC时应用程序出现的停顿;但由于可能和应用程序并发执行,所以会降低CPU对应用的处理能力。
-Xloggc:file
与-verbose:gc功能类似,只是将每次GC事件的相关情况记录到一个文件中,文件的位置最好在本地,以避免网络的潜在问题。
若与verbose命令同时出现在命令行中,则以-Xloggc为准。
-Xprof
跟踪正运行的程序,并将跟踪数据在标准输出输出;适合于开发环境调试。
-Xrs
减少jvm对操作系统信号(signals)的使用,该参数从1.3.1开始有效;
从jdk1.3.0开始,jvm允许程序在关闭之前还可以执行一些代码(比如关闭数据库的连接池),即使jvm被突然终止;
jvm关闭工具通过监控控制台的相关事件而满足以上的功能;更确切的说,通知在关闭工具执行之前,先注册控制台的控制handler,然后对CTRL_C_EVENT, CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENT, and CTRL_SHUTDOWN_EVENT这几类事件直接返回true。
但如果jvm以服务的形式在后台运行(比如servlet引擎),他能接收CTRL_LOGOFF_EVENT事件,但此时并不需要初始化关闭程序;为了避免类似冲突的再次出现,从jdk1.3.1开始提供-Xrs参数;当此参数被设置之后,jvm将不接收控制台的控制handler,也就是说他不监控和处理CTRL_C_EVENT, CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENT, or CTRL_SHUTDOWN_EVENT事件。
上面这些参数中,比如 -Xms、-Xmx
都是我们性能优化中很重要的参数;-Xprof、-Xloggc:file
等都是在没有专业跟踪工具情况下排错的好手;
-XX表示的非Stable参数
用-XX作为前缀的参数列表在 JVM 中可能是不健壮的,SUN 也不推荐使用,后续可能会在没有通知的情况下就直接取消了;但是由于这些参数中的确有很多是对我们很有用的,比如我们经常会见到的-XX:PermSize、-XX:MaxPermSize
等等。
以 -XX 表示的非 Stable 参数, JVM(Hotspot)中主要的参数可以大致分为3类
- 性能参数(Performance Options):用于JVM的性能调优和内存分配控制,如初始化内存大小的设置;
- 行为参数(Behavioral Options):用于改变JVM的基础行为,如GC的方式和算法的选择;
- 调试参数(Debugging Options):用于监控、打印、输出等jvm参数,用于显示jvm更加详细的信息;
对于非Stable参数,使用方法有4种:
-XX:+<option>
启用选项-XX:-<option>
不启用选项-XX:<option>=<number>
给选项设置一个数字类型值,可跟单位,例如 32k, 1024m, 2g-XX:<option>=<string>
给选项设置一个字符串值,例如-XX:HeapDumpPath=./dump.core
性能参数
性能参数往往用来定义内存分配的大小和比例,相比于行为参数和调试参数,一个比较明显的区别是性能参数后面往往跟的有数值,常用如下:
参数及其默认值 | 描述 |
---|---|
-XX:NewSize=2.125m |
新生代对象生成时占用内存的默认值 |
-XX:MaxNewSize=size |
新生成对象能占用内存的最大值 |
-XX:MaxPermSize=64m |
方法区所能占用的最大内存(非堆内存) |
-XX:PermSize=64m |
方法区分配的初始内存 |
-XX:MaxTenuringThreshold=15 |
对象在新生代存活区切换的次数(坚持过MinorGC的次数,每坚持过一次,该值就增加1),大于该值会进入老年代(年龄阈值) |
-XX:MaxHeapFreeRatio=70 |
GC后java堆中空闲量占的最大比例,大于该值,则堆内存会减少 |
-XX:MinHeapFreeRatio=40 |
GC后java堆中空闲量占的最小比例,小于该值,则堆内存会增加 |
-XX:NewRatio=2 |
新生代内存容量与老生代内存容量的比例 |
-XX:ReservedCodeCacheSize= 32m |
保留代码占用的内存容量 |
-XX:ThreadStackSize=512 |
设置线程栈大小,若为0则使用系统默认值 |
-XX:LargePageSizeInBytes=4m |
设置用于Java堆的大页面尺寸 |
-XX:PretenureSizeThreshold= size |
大于该值的对象直接晋升入老年代(这种对象少用为好) |
-XX:SurvivorRatio=8 |
Eden区域Survivor区的容量比值,如默认值为8,代表Eden:Survivor1:Survivor2=8:1:1 |
行为参数
行为参数主要用来选择使用什么样的垃圾收集器组合,以及控制运行过程中的GC策略等
参数及其默认值 | 描述 |
---|---|
-XX:+UseSerialGC |
启用串行GC,即采用Serial+Serial Old模式 |
-XX:+UseParallelGC |
启用并行GC,即采用Parallel Scavenge+Serial Old收集器组合(-Server模式下的默认组合) |
-XX:GCTimeRatio=99 |
设置用户执行时间占总时间的比例(默认值99,即1%的时间用于GC) |
-XX:MaxGCPauseMillis=time |
设置GC的最大停顿时间(这个参数只对Parallel Scavenge有效) |
-XX:+UseParNewGC |
使用ParNew+Serial Old收集器组合 |
-XX:ParallelGCThreads |
设置执行内存回收的线程数,在+UseParNewGC的情况下使用 |
-XX:+UseParallelOldGC |
使用Parallel Scavenge +Parallel Old组合收集器 |
-XX:+UseConcMarkSweepGC |
使用ParNew+CMS+Serial Old组合并发收集,优先使用ParNew+CMS,当用户线程内存不足时,采用备用方案Serial Old收集。 |
-XX:-DisableExplicitGC |
禁止调用System.gc();但jvm的gc仍然有效 |
-XX:+ScavengeBeforeFullGC |
新生代GC优先于Full GC执行 |
上面表格中黑体的-XX:+UseSerialGC
、-XX:+UseParallelGC
、-XX:+UseConcMarkSweepGC
代表着jvm中GC执行的三种方式,即串行、并行、并发
- 串行(SerialGC)是jvm的默认GC方式,一般适用于小型应用和单处理器,算法比较简单,GC效率也较高,但可能会给应用带来停顿;
- 并行(ParallelGC)是指GC运行时,对应用程序运行没有影响,GC和app两者的线程在并发执行,这样可以最大限度不影响app的运行;
- 并发(ConcMarkSweepGC)是指多个线程并发执行GC,一般适用于多处理器系统中,可以提高GC的效率,但算法复杂,系统消耗较大;
调试参数
调试参数,主要用于监控和打印GC的信息
参数及其默认值 | 描述 |
---|---|
-XX:-CITime |
打印消耗在JIT编译的时间 |
-XX:ErrorFile=./hs_err_pid<pid>.log |
保存错误日志或者数据到文件中 |
-XX:-ExtendedDTraceProbes |
开启solaris特有的dtrace探针 |
-XX:HeapDumpPath=./java_pid<pid>.hprof |
指定导出堆信息时的路径或文件名 |
-XX:-HeapDumpOnOutOfMemoryError |
当首次遭遇OOM时导出此时堆中相关信息 |
-XX:OnError="<cmd args>;<cmd args>" |
出现致命ERROR之后运行自定义命令 |
-XX:OnOutOfMemoryError="<cmd args>;<cmd args>" |
当首次遭遇OOM时执行自定义命令 |
-XX:-PrintClassHistogram |
遇到Ctrl-Break后打印类实例的柱状信息,与jmap -histo功能相同 |
-XX:-PrintConcurrentLocks |
遇到Ctrl-Break后打印并发锁的相关信息,与jstack -l功能相同 |
-XX:-PrintCommandLineFlags |
打印在命令行中出现过的标记 |
-XX:-PrintCompilation |
当一个方法被编译时打印相关信息 |
-XX:-PrintGC |
每次GC时打印相关信息 |
-XX:-PrintGC Details |
每次GC时打印详细信息 |
-XX:-PrintGCTimeStamps |
打印每次GC的时间戳 |
-XX:-TraceClassLoading |
跟踪类的加载信息 |
-XX:-TraceClassLoadingPreorder |
跟踪被引用到的所有类的加载信息 |
-XX:-TraceClassResolution |
跟踪常量池 |
-XX:-TraceClassUnloading |
跟踪类的卸载信息 |
-XX:-TraceLoaderConstraints |
跟踪类加载器约束的相关信息 |
上面表格中黑体的三个参数代表着jvm中GC执行的三种方式,即串行、并行、并发;
串行(SerialGC)是jvm的默认GC方式,一般适用于小型应用和单处理器,算法比较简单,GC效率也较高,但可能会给应用带来停顿;
并行(ParallelGC)是指GC运行时,对应用程序运行没有影响,GC和app两者的线程在并发执行,这样可以最大限度不影响app的运行;
并发(ConcMarkSweepGC)是指多个线程并发执行GC,一般适用于多处理器系统中,可以提高GC的效率,但算法复杂,系统消耗较大;
设置这些参数的一些心得
- Oracle 官方推荐堆的初始化大小与堆可设置的最大值一般是相等的,即
Xms = Xmx
,因为起始堆内存太小(Xms),会导致启动初期频繁 GC,起始堆内存较大(Xmx)有助于减少 GC 次数 - 调试的时候设置一些打印参数,如
-XX:+PrintClassHistogram -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintHeapAtGC -Xloggc:log/gc.log
,这样可以从 gc.log 里看出一些端倪出来 - 系统停顿时间过长可能是 GC 的问题也可能是程序的问题,多用 jmap 和 jstack 查看,或者 killall -3 Java,然后查看 Java 控制台日志,能看出很多问题
- 采用并发回收时,年轻代小一点,年老代要大,因为年老大用的是并发回收,即使时间长点也不会影响其他程序继续运行,网站不会停顿
- 仔细了解自己的应用,如果用了缓存,那么年老代应该大一些,缓存的 HashMap 不应该无限制长,建议采用 LRU 算法的 Map 做缓存,LRUMap 的最大长度也要根据实际情况设定
要设置好各种 JVM 参数,还可以对 server 进行压测, 预估自己的业务量,设定好一些 JVM 参数进行压测看下这些设置好的 JVM 参数是否能满足要求