文章目录
- 1、JVM参数选项类型
- 1.1、标准参数选项
- 1.2、非标准参数选项
- 1.3、非稳定参数选项
- 2、添加JVM参数的方式
- 3、常用JVM参数选项
- 4、通过Java代码获取JVM参数
- 5、小结
熟悉JVM参数对于系统调优是非常重要的。比如一个高流量的延迟的电子交易平台,它要求的响应时间都是毫秒级的。要获得适合的参数组合需要大量的分析和不断地尝试,更依赖交易系统的特性。
本帖将主要讲解JVM的运行时参数的分类及其使用方式。
1、JVM参数选项类型
JVM参数总体上来说分为三大类,分别是标准参数选项、非标准参数选项和非稳定参数选项,下面分别详细介绍三大参数类型。
1.1、标准参数选项
所有的JVM都必须实现标准参数的功能,而且向后兼容。标准参数是相对比较稳定的参数,后续版本基本不会发生变化,参数以“-”开头,例如大家常见的“-version”参数就是标准参数。获取标准参数的命令是在终端输入“java”或者“java -help”命令即可,获取结果如下表所示:
需要注意的是HotSpot虚拟机的两种模式,分别是Server和Client,分别通过-server和-client模式设置。
在32位Windows系统上,默认使用Client类型的JVM。要想使用Server模式,则机器配置至少有2个以上的CPU和2GB以上的物理内存。Client模式适用于对内存要求较小的桌面应用程序,默认使用Serial串行垃圾收集器。
64位机器上只支持Server模式的JVM,适用于需要大内存的应用程序,默认使用并行垃圾收集器。
1.2、非标准参数选项
我们知道JVM可以有不同的生产厂商,非标准参数的意思是并不保证所有JVM都对非标准参数进行实现,即只能被部分JVM识别且不保证向后兼容,功能相对来说也是比较稳定的,但是后续版本有可能会变更,参数以“-X”开头。可以用java -X来检索非标准参数,不能保证所有参数都可以被检索出来,例如其中就没有-Xcomp。下表列出了常见的非标准参数。
特别注意的是-Xint参数表示禁用JIT,所有的字节码都被解释执行,这个模式下系统启动最快,但是执行效率最低。-Xcomp表示JVM采用编译模式,代码执行很快,但是启动会比较慢。-Xmixed表示JVM采用混合模式,启动速度较快,让JIT根据程序运行的情况,对热点代码实行检测和编译。
虽然-Xms、-Xmx和-Xss三个参数归属于-X参数选项,但是这三个参数的执行效果分别等同于非稳定参数中的-XX:InitialHeapSize、-XX:MaxHeapSize和-XX:ThreadStackSize。
1.3、非稳定参数选项
非稳定参数选项以-XX开头,也属于非标准参数,相对不稳定,在JVM中是不健壮的,也可能会突然直接取消某项参数,主要用于JVM调优和调试。但是这些参数中有很多参数对于JVM调优很有用处,所以也是使用最多的参数选项。
-XX参数又分为布尔类型参数和非布尔类型参数。布尔类型的格式为-XX:+/-,-XX:+表示启用option,-XX:-表示禁用option。例如-XX:+UseParallelGC表示开启ParallelGC垃圾收集器,-XX:-UseParallelGC表示关闭ParallelGC垃圾收集器,有些参数是默认开启的,调优的时候可以考虑关闭某些参数。
非布尔类型的参数也可以理解为Key-Value型的参数,可以分为数值类型和非数值类型。数值类型格式为-XX:=,number可以带上单位(k、K表示千字节,m、M表示兆,或者使用更大的内存单位g、G),例如-XX:NewSize=1024m表示设置新生代初始大小为1024MB。非数值类型格式为-XX:=,例如-XX:HeapDumpPath=/usr/local/heapdump.hprof用来指定heap转存文件的存储路径。
通过“java -XX:+PrintFlagsFinal”命令可以查看所有的-XX参数,如下图所示,篇幅原因截取部分截图。
上图最后一列参数的取值有多种,如下所示:
- (1)product表示该类型参数是官方支持的,属于JVM内部选项。
- (2)rw表示可动态写入。
- (3)C1表示Client JIT编译器。
- (4)C2表示Server JIT编译器。
- (5)pd表示平台独立。
- (6)lp64表示仅支持64位JVM。
- (7)manageable表示可以运行时修改。
- (8)diagnostic表示用于JVM调试。
- (9)experimental表示非官方支持的参数。
默认不包含diagnostic和experimental两种类型,想要包含该类型的参数可以配合参数-XX:+UnlockDiagnosticVMOptions和-XX:+UnlockExperimentalVMOptions使用,例如java-XX:+PrintFlagsFinal -XX:+UnlockDiagnosticVMOptions命令结果如下(部分结果),包含了diagnostic类型的参数。同理可以添加-XX:+UnlockExperimentalVMOptions参数用于包含experimental类型的参数,不再演示。
2、添加JVM参数的方式
在工作中经常需要配置JVM参数,一般有以下几种方式:
1、IDEA界面配置
鼠标右键选中目标工程,选择“Run”→“Edit Configurations”选项,选中要添加JVM参数的Application,然后在Configuration里面的VM options中输入想要添加的JVM参数即可,如下图所示,例如填入-Xmx256m,这样就可以设置运行时最大内存为256MB。
2、通过java命令配置
通过java命令运行class或者jar包的时候也可以添加JVM参数,一般多用于工程测试,如下所示:
//运行jar包时添加JVM参数java -Xms128m -Xmx256m -jar demo.jar//运行类的字节码文件时添加JVM参数java -Xms128m -Xmx256m 类名
3、通过web服务器配置
Linux系统下可以在tomcat/bin/catalina.sh中添加如下JVM配置。
JAVA_OPTS="-Xms512M -Xmx1024M"
Windows系统下可以在catalina.bat中添加如下配置。
set"JAVA_OPTS=-Xms512M -Xmx1024M"
4、通过jinfo命令配置
3、常用JVM参数选项
JVM参数选项那么多,在工作中有很多参数是很少用到的,这里汇总了几大常用的参数分类,如下所示:
(1)输出设置的-XX参数以及参数值的参数选项如下表所示:
(2)堆、栈、方法区等内存大小设置的参数选项如下表所示:
(3)OutOfMemory相关的参数选项如下表所示:
-XX:OnOutOfMemoryError表示当发生内存溢出的时候,还可以让JVM调用任一个shell脚本。大多数时候,内存溢出并不会导致整个应用都挂掉,但是最好还是把应用重启一下,因为一旦发生了内存溢出,可能会让应用处于一种不稳定的状态,一个不稳定的应用可能会提供错误的响应。例如使用以下命令:
-XX:OnOutOfMemoryError=/opt/Server/restart.sh
当给JVM传递上述参数的时候,如果发生了内存溢出,JVM会调用/opt/Server/restart.sh这个脚本,在这个脚本中可以去用优雅的办法来重启应用。restart.sh脚本如下所示。
(4)垃圾收集器相关的参数选项因垃圾收集器的不同而不同,关于垃圾收集器的分类以及配合使用。使用-XX:+PrintCommandLineFlags查看命令行相关参数,从中可以查看到当前系统使用的垃圾收集器,也可以使用命令行指令jinfo查看。
Serial收集器作为HotSpot中Client模式下的默认新生代垃圾收集器。Serial Old收集器是运行在Client模式下默认的老年代的垃圾收集器。-XX:+UseSerialGC参数可以指定新生代和老年代都使用串行收集器,表示新生代用Serial GC,且老年代用Serial Old收集器。可以获得最高的单线程收集效率。现在已经很少使用Serial收集器了。
ParNew收集器可以使用-XX:+UseParNewGC参数指定。它表示新生代使用并行收集器,不影响老年代。Parallel收集器的相关JVM参数选项如下表:
CMS收集器的相关JVM参数选项如下表所示:
需要注意的是JDK 9新特性中CMS被标记为Deprecate了,如果对JDK 9及以上版本的HotSpot虚拟机使用参数-XX:+UseConcMarkSweepGC来开启CMS收集器的话,用户会收到一个警告信息,提示CMS未来将会被废弃。JDK 14新特性中删除了CMS垃圾收集器,如果在JDK 14中使用-XX:+UseConcMarkSweepGC的话,JVM不会报错,只是给出一个warning信息,但是不会exit。JVM会自动回退以默认GC方式启动JVM。
G1收集器的相关JVM参数选项如下表所示:
G1收集器主要涉及Mixed GC,Mixed GC会回收新生代和部分老年代,G1关于Mixed GC调优常用参数选项如下表所示:
(5)GC日志相关的参数选项如下表所示:
(6)其他常用的参数选项如下表所示:
4、通过Java代码获取JVM参数
Java提供了java.lang.management包用于监视和管理JVM和Java运行时中的其他组件,它允许本地和远程监控和管理运行的JVM,会经常使用到其中的ManagementFactory类。另外还有Runtime类也可以获取一些内存、CPU核数等相关的数据。通过这些API可以监控我们的应用服务器的堆内存使用情况,也可以设置一些阈值进行报警等处理,代码清单如下演示了Java代码获取应用的内存使用情况:
运行结果如下,可以看到堆内存的各项信息:
5、小结
讲解了JVM运行时参数,JVM参数对于系统调优是非常重要的,参数分为三类,分别是标准参数选项、非标准参数选项和非稳定参数选项。标准参数是所有的JVM实现都必须要实现的参数,不同的JVM拥有相同的参数功能。非标准参数无法保证所有的JVM都会有对应的实现,该类型参数一般以“-X”开头。非稳定参数在JVM中是不健壮的,属于试验性质的参数,有可能在不同的JVM版本中会被取消,该类型参数一般以“-XX”开头,对于JVM调优有很大的用处。