我们可以通过启动 Java 命令时指定不同的 JVM 参数,让 JVM 调整自己的运行状态和行为,内存管理和垃圾回收的 GC 算法,添加和处理调试和诊断信息等等。
直接通过命令启动java
java [options] classname [args]
java [options] -jar filename [args]
-
[options]
部分称为 “JVM 选项”,对应 IDE 中的 VM options, 可用jps -v
查看。 -
[args]
部分是指 “传给main函数的参数”, 对应 IDE 中的 Program arguments, 可用jps -m
查看。
如果是使用 Tomcat 之类自带 startup.sh 等启动脚本的程序,我们一般把相关参数都放到一个脚本定义的 JAVA_OPTS 环境变量中,最后脚本启动 JVM 时会把 JAVA_OPTS 变量里的所有参数都加到命令的合适位置。比如设置jvm参数-Xms -Xmx
之类的堆大小参数。
对于springboot来说设置JAVA_TOOL_OPTIONS
就可以给jvm设置参数了。
在命令行输入java就能看到参数列表说明:
- Java和JDK内置工具在指定参数时都是以一个
-
开头为标准参数,所有的JVM都要实现这些参数,并且向后兼容。 - -D设置系统属性(环境变量),例如
-Dfile.encoding=UTF-8
、-Duser.timezone=GMT+08
- 以
-X
开头为非标准参数,基本都是传给JVM的,默认JVM实现这些参数的功能,但是并不保证所有的JVM都满足,且不保证向后兼容。 - 以
-XX:
开头为为稳定参数,专门用于控制JVM的行为,跟具体的JVM实现相关,随时可能会在下一个版本取消。 -
-XX:+-Flags
形式,+-
是对布尔值进行开关 -
-XX:key=value
形式,指定某个选项的值。
查看默认的所有系统属性
java -XshowSettings:properties -version
查看VM设置
java -XshowSettings:vm -version
查看当前 JDK/JRE 的默认显示语言设置
java -XshowSettings:locale -version
系统属性参数
系统属性,有时候也叫环境变量,例如直接给 JVM 传递指定的系统属性参数,需要使用 -Dkey=value
这种形式,此时如果系统的环境变量里不管有没有指定这个参数,都会以这里的为准。
-D设置系统属性(环境变量),例如-Dfile.encoding=UTF-8
、-Duser.timezone=GMT+08
还有常见的,我们使用 mvn 脚本去执行编译的同时,如果不想编译和执行单元测试代码:
$ mvn package -Djava.test.skip=true
或者
$ mvn package -DskipTests
等等,很多地方会用设置系统属性的方式去传递数据给Java程序,而不是直接用程序参数的方式。
运行模式参数
JVM有两种运行模式
-
-server
:特点:启动速度比较慢,但运行性能和内存管理效率很高,用于生产环境。在具有64位能力的jdk环境下默认开启此模式。 -
-client
:特点: 启动速度比较快,但运行时性能和内存管理效率不高,通常用于客户端应用程序或者pc应用开发和调试。
堆内存设置参数
JVM总内存=堆内存+栈+非堆+堆外内存
-
-Xms
: 指定堆的初始大小,默认物理内存的1/64。如-Xms2g
。操作系统并不是实际分配的初始大小,而是GC先规划好,用到在分配。生产环境需要-Xms
和-Xmx
一致,否则应用刚启动就会有FullGC,两者配置不一致,堆扩容可能会导致性能抖动。默认空余堆内存小于40%时,JVM就会增大堆直到-Mmx
。空余堆内存大于70%时,JVM会减少堆直到-Xms
。 -
-Xmx
:指定堆的最大分配内存。默认是物理内存的1/4。如-Xmx2g
。这个内存只是堆内存,不包括栈内存,也不包括堆外使用的内存。 -
-Xmn
:等价于-XX:NewSize
,新生代的大小。-Xmx
--Xmn
就能获得老年代大小。使用G1垃圾收集器不应该设置该选项,在其他的某些业务场景下可以设置。官方建议设置位Xmx
的1/2-1/4。 -
-XX:PermSize
、-XX:MaxPermSize=size
, 设置永久代最小、最大大小。这是 JDK1.7 之前使用的。Java8 默认允许的 Meta 空间无限大,此参数无效。 - ``-XX:MetaspaceSize
、
-XX:MaxMetaspaceSize=size`,元空间最小、最大大小,Java8 默认不限制 Meta 空间, 一般不允许设置该选项。 -
-XX:MaxDirectMemorySize=size
,系统可以使用的最大堆外内存,这个参数跟-Dsun.nio.MaxDirectMemorySize
效果相同。 -
-XX:NewRatio
:设置新生代和老年代的比值。如:为3,表示年轻代与老年代比值为1:3
-XX:SurvivorRatio:新生代中Eden区与两个Survivor区的比值。注意Survivor区有两个。如:为3,表示Eden:Survivor=3:2,一个Survivor区占整个新生代的1/5。 -
-XX:MaxTenuringThreshold
:设置转入老年代的存活次数。如果是0,则直接跳过新生代进入老年代。 -
-Xss
, 设置每个线程栈的内存大小。 例如-Xss1m
指定线程栈为 1MB,与-XX:ThreadStackSize=1m
等价。在相同物理内存下,减小这个值能生成更多的线程,当然操作系统对一个进程内的线程数还是有限制的,不能无限生成。线程栈的大小是个双刃剑,如果设置过小,可能会出现栈溢出,特别是在该线程内有递归、大的循环时出现溢出的可能性更大,如果该值设置过大,就有影响到创建栈的数量,如果是多线程的应用,就会出现内存溢出的错误。
Xmx最佳实践:推荐配置系统或者容器可用内存的60-80%。比如说系统有 8G 物理内存,系统自己可能会用掉一点,大概还有 7.5G 可以用,那么建议配置
-Xmx6g 说明:xmx : 7.5G*0.8 = 6G,如果知道系统里有明确使用堆外内存的地方,还需要进一步降低这个值。
GC日志相关参数
-
-verbose:gc
:和其他 GC 参数组合使用, 在 GC 日志中输出详细的GC信息。 包括每次 GC 前后各个内存池的大小,堆内存的大小,提升到老年代的大小,以及消耗的时间。此参数支持在运行过程中动态开关。比如使用 jcmd, jinfo, 以及使用 JMX 技术的其他客户端。 -
-XX:+PrintGCDetails
和-XX:+PrintGCTimeStamps
:打印 GC 细节与发生时间。请关注我们后续的 GC 课程章节。 -
-Xloggc:file
:与-verbose:gc
功能类似,只是将每次 GC 事件的相关情况记录到一个文件中,文件的位置最好在本地,以避免网络的潜在问题。若与 verbose:gc 命令同时出现在命令行中,则以 -Xloggc 为准。
示例:
export JAVA_OPTS="-Xms28g -Xmx28g -Xss1m \
-verbosegc -XX:+UseG1GC -XX:MaxGCPauseMillis=200 \
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/usr/local/"
垃圾收集器相关参数
垃圾回收器是 JVM 性能分析和调优的核心内容之一,也是近几个 JDK 版本大力发展和改进的地方。通过不同的 GC 算法和参数组合,配合其他调优手段,我们可以把系统精确校验到性能最佳状态。
-
-XX:+UseG1GC
:使用 G1 垃圾回收器 -
-XX:+UseConcMarkSweepGC
:使用 CMS 垃圾回收器 -
-XX:+UseSerialGC
:使用串行垃圾回收器 -
-XX:+UseParallelGC
:使用并行垃圾回收器
特殊情况执行脚本的参数
除了上面介绍的一些 JVM 参数,还有一些用于出现问题时提供诊断信息之类的参数。
-
-XX:+-HeapDumpOnOutOfMemoryError
选项, 当OutOfMemoryError
产生,即内存溢出(堆内存或持久代)时,自动 Dump 堆内存。 因为在运行时并没有什么开销, 所以在生产机器上是可以使用的。 示例用法:java -XX:+HeapDumpOnOutOfMemoryError -Xmx256m ConsumeHeap
-
-XX:HeapDumpPath
选项, 与HeapDumpOnOutOfMemoryError
搭配使用, 指定内存溢出时 Dump 文件的目录。 如果没有指定则默认为启动 Java 程序的工作目录。 示例用法:java -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/usr/local/ ConsumeHeap
自动 Dump 的 hprof 文件会存储到/usr/local/
目录下。 -
-XX:OnError
选项, 发生致命错误时(fatal error)执行的脚本。 例如, 写一个脚本来记录出错时间, 执行一些命令, 或者 curl 一下某个在线报警的url. 示例用法:java -XX:OnError="gdb - %p" MyApp
可以发现有一个%p
的格式化字符串,表示进程 PID。 -
-XX:OnOutOfMemoryError
选项, 抛出 OutOfMemoryError 错误时执行的脚本。 -
-XX:ErrorFile=filename
选项, 致命错误的日志文件名,绝对路径或者相对路径。
官方JVM参数清单
Java HotSpot VM Options (oracle.com)