概览
本篇博文中将会探索一些常用的 JVM Options。
显示指定堆内存参数:-Xms 和 -Xmx
常用的性能相关实践就是应应用程序的需求来初始化堆内存。下面两个参数可以用于指定最小和最大堆内存。
-Xms<heap size>[unit]
-Xmx<heap size>[unit]
其中的 unit 表示需要初始化堆内存大小的单位,'g' 表示 GB,'m' 表示 MB 和 'k' 表示 KB。
比如我们想要指定虚拟机堆内存最小 2GB 和最大 5GB,可以这样写:
-Xms2G -Xmx5G
自 Java8 起,Metaspace 的大小是没有定义的。一旦 Metaspace 达到全局的限制,JVM 就会自动增加它。然而,为了克服不必要的稳定性因素,建议设置 Metaspace 大小:
-XX:MaxMetaspaceSize=<metaspace size>[unit]
其中的 metaspace size 表示我们可以分配给 Metaspace 的最大内存大小。
根据 Oracle 准则,在总可用内存后的第二个最具有影响力的因素就是为年轻代(YG, Young Generation)保留的堆内存的比例。YG 的最小大小默认为 1310MB,最大大小默认无限制。
我们也可以通过显示设置:
-XX:NewSize=<young size>[unit]
-XX:MaxNewSize=<young size>[unit]
垃圾回收
为了提高应用程序的稳定性,最关键的是选择一个正确的垃圾回收
(GC, Garbage Collection)算法。JVM 有以下四种 GC 的实现:
- 序列垃圾回收器(Serial Garbage Collector)
- 并行垃圾回收器(Parallel Garbage Collector)
- CMS 垃圾回收器(CMS Garbage Collector)
- G1 垃圾回收器(G1 Garbage Collector)
CMS:Concurrent Mark Sweep,并发标记擦除回收器
G1: Garbage-First,垃圾优先回收器,主要面向大内存多核心的机器
可以通过以下参数来指定某个实现:
-XX:+UseSerialGC
-XX:+UseParallelGC
-XX:+UseConcMarkSweepGC -XX:+UseParNewGC
-XX:+UseG1GC
GC 记录
想要监控应用程序的健康,我们应该经常检查 JVM 的垃圾回收器的性能。最简单的办法就是以人类可读的形式来记录 GC 的活动。
可使用一下参数就可以记录 GC 的活动信息:
-XX:+UseGCLogFileRotation
-XX:NumberOfGCLogFiles=<number of log files>
-XX:GCLogFileSize=<file size>[unit]
-Xloggc:/path/to/gc.log
UseGCLogFileRotation
:表示日志文件的滚动策略(Rolling Policy),类似于 log4j,s4lj。不过似乎并不被建议使用。
NUmberOfGCLogFiles
:表示一个应用程序的生命周期中可以被写入的日志文件的最大数量。GCLogFileSize
指定日志文件的大小。最后的 loggc
表示日志文件的位置,被 log:gc
替代。
需要注意的是,这里有另外两个的 JVM 参数用来在日志文件中打印日期时间戳,-XX:+PrintGCTimeStamps 和 -XX:+PrintGCDateStamps。
例如,你想要设置 GC 日志文件的最大数量为 100,每个文件的最大大小为 50MB,并存储在 /home/user/log/
目录下,可以使用以下参数:
-XX:+UseGCLogFileRotation
-XX:NumberOfGCLogFiles=100
-XX:GCLogFileSize=50M
-Xloggc:/home/user/log/gc.log
然而这里有一个问题,就是需要一个额外的守护线程始终用于在后台监视系统时间。这可能导致性能瓶颈,所以建议不要在生产环境下使用这些参数。
注意:某些参数在新版的 JVM 中已经过时了,甚至不能够识别。
内存溢出处理
大型应用程序面临内存溢出的问题是非常普遍的,最终的结果就是导致应用程序崩溃。这是非常严重的情况,且很难通过复现来解决问题。
这就是为什么 JVM 会提供一些参数,供我们导出堆内存到物理文件,最后找出溢出的位置:
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=./java_pid<pid>.hprof
-XX:OnOutOfMemoryError="<cmd args>;<cmd args>"
-XX:+UseGCOverHeadLimit
这里一一解释一下以上参数:
-
HeapDumpOnOutOfMemoryError:表示一旦发生了
OutOfMemoryError
错误,JVM 就导出堆内存信息到物理文件中。 -
HeapDumpPath:表示需要写入的文件的存放位置。文件名可任意指定。若 JVM 在文件名中找到了
标签,那么当前导致内存溢出错误的进程的 进程 id
将会设置到文件名中。 -
OnOutOfMemoryError:用于一旦发生了内存溢出错误发出需要执行的紧急命令。在
cmd args
中应该设置一些合适的命令,例如,只要内存溢出了就重启服务器,我们可以设置如下参数:
-XX:OnOutOfMemoryError="shutdown -r"
- UseGCOverHeadLimit:是一项策略,用于限制在
OutOfMemoryError
错误之前,虚拟机在GC
中消耗的时间。
32 / 64 位
在 32 位和 64 位的包都已经安装的操作系统环境,JVM 会自动选择 32 位环境的包来实际运行。
我们可以用以下参数来手动 64 位的包作为运行环境:
-d<OS bit>
OS bit
可以是 32,也可以是 64。更多相关信息可以点击这里。
杂项
- -server:启用 "Server Hotspot VM",这个参数在 64 位的虚拟机中是默认设置的。