JVM常用的一些参数
一、JVM参数使用示例
1.1 参数概述
Java大概有一千多个的配置参数,这些参数在JVM,GC,环境变量,开发测试,问题排查等方面都有涉及,运行java命令,可以看到参数列表说明。
当然,我们不可能把所有的参数都列完,其实在我们日常使用过程中,用到的参数很少,比如XMX XMS等几个命令。
PS C:\Users\jixiaobo> java
用法: java [-options] class [args...]
(执行类)
或 java [-options] -jar jarfile [args...]
(执行 jar 文件)
其中选项包括:
-d32 使用 32 位数据模型 (如果可用)
-d64 使用 64 位数据模型 (如果可用)
-server 选择 "server" VM
默认 VM 是 server.
-cp <目录和 zip/jar 文件的类搜索路径>
-classpath <目录和 zip/jar 文件的类搜索路径>
用 ; 分隔的目录, JAR 档案
和 ZIP 档案列表, 用于搜索类文件。
-D<名称>=<值>
设置系统属性
-verbose:[class|gc|jni]
启用详细输出
-version 输出产品版本并退出
-version:<值>
警告: 此功能已过时, 将在
未来发行版中删除。
需要指定的版本才能运行
-showversion 输出产品版本并继续
-jre-restrict-search | -no-jre-restrict-search
警告: 此功能已过时, 将在
未来发行版中删除。
在版本搜索中包括/排除用户专用 JRE
-? -help 输出此帮助消息
-X 输出非标准选项的帮助
-ea[:<packagename>...|:<classname>]
-enableassertions[:<packagename>...|:<classname>]
按指定的粒度启用断言
-da[:<packagename>...|:<classname>]
-disableassertions[:<packagename>...|:<classname>]
禁用具有指定粒度的断言
-esa | -enablesystemassertions
启用系统断言
-dsa | -disablesystemassertions
禁用系统断言
-agentlib:<libname>[=<选项>]
加载本机代理库 <libname>, 例如 -agentlib:hprof
另请参阅 -agentlib:jdwp=help 和 -agentlib:hprof=help
-agentpath:<pathname>[=<选项>]
按完整路径名加载本机代理库
-javaagent:<jarpath>[=<选项>]
加载 Java 编程语言代理, 请参阅 java.lang.instrument
-splash:<imagepath>
使用指定的图像显示启动屏幕
对于JVM的启动参数从格式上大致分为
VM 的启动参数, 从形式上可以简单分为:
- 以-开头为标准参数,所有的 JVM 都要实现这些参数,并且向后兼容。
- 以-X开头为非标准参数, 基本都是传给 JVM 的,默认 JVM 实现这些参数的功能,但是并不保证所有 JVM 实现都满足,且不保证向后兼容。
- 以-XX:开头为非稳定参数, 专门用于控制 JVM 的行为,跟具体的 JVM 实现有关,随时可能会在下个版本取消。
- XX:±Flags 形式, ± 是对布尔值进行开关。
- XX:key=value 形式, 指定某个选项的值。
1.2 参数使用
- classname/jar包使用方式
java [options] classname [args]
java [options] -jar filename [args]
- [options] 部分称为 "JVM 选项",对应 IDE 中的 VM options, 可用 jps -v 查看。
- [args] 部分是指 "传给main函数的参数", 对应 IDE 中的 Program arguments, 可用 jps -m 查看
- IDEA执行方式
如果是在 IDEA 之类的 IDE 里运行的话,则可以在“Run/Debug Configurations”里看到 VM 选项和程序参数两个可以输入参数的地方,直接输入即可。
- 其他
如docker、tomcat中使用,在dockerfile,startup.sh中添加以上参数即可。
二、 系统属性参数
我们常见的设置 $JAVA_HOME 就是一个环境变量,只要在当前命令执行的上下文里有这个环境变量,就可以在启动的任意程序里,通过相关 API 拿到这个参数,比如 Java 里:
System.getProperty(“key”)来获取这个变量的值,这样就可以做到多个不同的应用进程可以共享这些变量,不用每个都重复设置,也可以实现简化 Java 命令行的长度(想想要是配置了 50 个参数多恐怖,放到环境变量里,可以简化启动输入的字符)
- 使用java -XshowSettings:properties -version
- java -XshowSettings:vm -version
还有常见的,我们使用 mvn 脚本去执行编译的同时,如果不想编译和执行单元测试代码:
$ mvn package -Djava.test.skip=true
三、 运行模式参数
- server:设置 JVM 使用 server 模式,特点是启动速度比较慢,但运行时性能和内存管理效率
很高,适用于生产环境。在具有 64 位能力的 JDK 环境下将默认启用该模式,而忽略 -client 参
数。 - client :JDK1.7 之前在32位的 x86 机器上的默认值是 -client 选项。设置 JVM 使用 client 模
式,特点是启动速度比较快,但运行时性能和内存管理效率不高,通常用于客户端应用程序或
者 PC 应用开发和调试。此外,我们知道 JVM 加载字节码后,可以解释执行,也可以编译成本
地代码再执行,所以可以配置 JVM 对字节码的处理模式: - Xint:在解释模式(interpreted mode)下运行,-Xint 标记会强制 JVM 解释执行所有的字节
码,这当然会降低运行速度,通常低10倍或更多。 - Xcomp:-Xcomp 参数与-Xint 正好相反,JVM 在第一次使用时会把所有的字节码编译成本地
代码,从而带来最大程度的优化。【注意预热】 - Xmixed:-Xmixed 是混合模式,将解释模式和编译模式进行混合使用,有 JVM 自己决定,这
是 JVM 的默认模式,也是推荐模式。 我们使用 java -version 可以看到 mixed mode 等信息。
四、堆内存设置参数
最常用的参数之一,常用参数有如下几个
- Xmx, 指定最大堆内存。 如 -Xmx4g. 这只是限制了 Heap 部分的最大值为4g。
这个内存不包括栈内存,也不包括堆外使用的内存。 - Xms, 指定堆内存空间的初始大小。 如 -Xms4g。 而且指定的内存大小,并
不是操作系统实际分配的初始值,而是GC先规划好,用到才分配。 专用服务
器上需要保持 –Xms 和 –Xmx 一致,否则应用刚启动可能就有好几个 FullGC。
当两者配置不一致时,堆内存扩容可能会导致性能抖动。 - Xmn, 等价于 -XX:NewSize,使用 G1 垃圾收集器 不应该 设置该选项,在其
他的某些业务场景下可以设置。官方建议设置为 -Xmx 的 1/2 ~ 1/4. - XX:MaxPermSize=size, 这是 JDK1.7 之前使用的。Java8 默认允许的
Meta空间无限大,此参数无效。 - XX:MaxMetaspaceSize=size, Java8 默认不限制 Meta 空间, 一般不允许设
置该选项。 - XX:MaxDirectMemorySize=size,系统可以使用的最大堆外内存,这个参
数跟 -Dsun.nio.MaxDirectMemorySize 效果相同。 - Xss, 设置每个线程栈的字节数。 例如 -Xss1m 指定线程栈为 1MB,与-
XX:ThreadStackSize=1m 等价
JVM 总内存=堆+栈+非堆+堆外内存。详情可参考系列文章JVM(二)内存模型
“Direct Memory”,一般来说是 Java NIO 使用的 Direct-X-Buffer(例如 DirectByteBuffer)所分配的 native memory,这个地方如果我们使用 netty 之类的框架,会产生大量的堆外内存。
五、GC 设置参数
常用的GC设置如下
- XX:+UseG1GC使用 G1 垃圾回收器
- XX:+UseConcMarkSweepGC使用 CMS 垃圾回收器
- XX:+UseSerialGC使用串行垃圾回收器
- XX:+UseParallelGC使用并行垃圾回收器
// Java 11+ - XX:+UnlockExperimentalVMOptions -XX:+UseZGC
// Java 12+ - XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC
六、分析诊断参数
在生产环境或性能压测环境里,我们用来分析和判断问题的重要数据来源之一就是 GC 日志,JVM 启动参数为我们提供了一些用于控制 GC 日志输出的选项。
- 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 选项, 致命错误的日志文件名,绝对路径或者相对路径。
- Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=1506,远程调试
七、JavaAgent 参数
Agent 是 JVM 中的一项黑科技, 可以通过无侵入方式来做很多事情,比如注入 AOP 代码,执行统计等等,权限非常大。这里简单介绍一下配置选项,一般用不到。
设置 agent 的语法如下:
- agentlib:libname[=options] 启用native方式的agent, 参考 LD_LIBRARY_PATH 路径。
- agentpath:pathname[=options] 启用native方式的agent。
- javaagent:jarpath[=options] 启用外部的agent库, 比如 pinpoint.jar 等等。
- Xnoagent 则是禁用所有 agent。
以下示例开启 CPU 使用时间抽样分析:
JAVA_OPTS="-agentlib:hprof=cpu=samples,file=cpu.samples.log"
其中 hprof 是 JDK 内置的一个性能分析器。cpu=samples 会抽样在各个方法消耗的时间占比, Java 进程退出后会将分析结果输出到文件。
八、参考链接
以上的常用参数会在后面的JVM系列中用到