总览
在本快速教程中,我们将探索可用于配置Java虚拟机的最常见的选项。
显式设定堆内存 –Xms和-Xmx选项
与性能有关的最常见实践之一是根据应用程序要求初始化堆内存。
这就是为什么我们应该指定最小和最大堆。以下参数可用于实现此目的:
-Xms<heap size>[unit]
-Xmx<heap size>[unit]
此处,unit表示要初始化内存(由堆大小指示)的单位。对于GB,单位可以标记为“g”,对于MB,单位可以标记为“m”,对于KB,单位可以标记为“k”。
例如,如果我们要为JVM分配最小2GB和最大5GB,我们需要编写:
-Xms2G -Xmx5G
从Java 8开始,未定义Metaspace的大小。一旦达到全局限制,JVM会自动增加它。但是,为了克服任何不必要的不稳定,我们可以使用以下方法设置元空间大小:
-XX:MaxMetaspaceSize=<metaspace size>[unit]
在这里,元空间大小表示我们要分配给元空间的内存。
根据Oracle指南,在总可用内存之后,第二大影响因素是为Young Generation保留的堆的比例。默认情况下,YG的最小大小为1310 MB,最大大小为无限。
我们可以明确地分配它们:
-XX:NewSize=<young size>[unit]
-XX:MaxNewSize=<young size>[unit]
垃圾收集
为了提高应用程序的稳定性,选择正确的垃圾收集算法至关重要。
JVM具有四种类型的GC实现:
- Serial Garbage Collector
- Parallel Garbage Collector
- CMS Garbage Collector - 从Java 9开始,不建议使用CMS垃圾收集器。此外,Java 14完全放弃了CMS支持。
- G1 Garbage Collector
可以使用以下参数声明这些实现:
-XX:+UseSerialGC
-XX:+UseParallelGC
-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 指定了日志文件滚动策略,与log4j,slf4j等非常相似。NumberOfGCLogFiles表示可以在单个应用程序生命周期内写入的最大日志文件数。GCLogFileSize指定文件的最大大小。最后,loggc表示其位置。
这里要注意的是,还有两个可用的JVM参数(-XX:+ PrintGCTimeStamps和 -XX:+ PrintGCDateStamps)可用于在GC日志中打印按日期标记的时间戳。
例如,如果我们要分配最多10个GC日志文件(每个文件的最大大小为50 MB)并将它们存储在“/home/user/log/”位置,则可以使用以下语法:
-XX:+UseGCLogFileRotation
-XX:NumberOfGCLogFiles=10
-XX:GCLogFileSize=50M
-Xloggc:/home/user/log/gc.log
但是,问题在于,总是在后台使用一个附加的守护程序线程来监视系统时间。此行为可能会产生一些性能瓶颈;因此,在生产中最好不要使用此参数。
处理内存不足
大型应用程序遇到内存不足错误非常普遍,而错误又导致应用程序崩溃。这是非常关键的情况,很难照搬以解决问题。
这就是JVM带有一些参数的原因,这些参数将堆内存快照转储到物理文件中,可用于以后查找泄漏:
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=./java_pid<pid>.hprof
-XX:OnOutOfMemoryError="< cmd args >;< cmd args >"
-XX:+UseGCOverheadLimit
这里有几点要注意:
- HeapDumpOnOutOfMemoryError指示JVM在OutOfMemoryError情况下将堆转储到物理文件中
- HeapDumpPath表示要写入文件的路径;可以提供任何文件名;但是,如果JVM在名称中找到 <pid> 标记,则导致内存不足错误的当前进程的进程ID将以.hprof格式附加到文件名中。
- OnOutOfMemoryError用于发出紧急命令以在出现内存不足错误时执行;在cmd args的空格中应使用正确的命令。例如,如果要在内存不足时立即重新启动服务器,则可以设置参数:
-XX:OnOutOfMemoryError="shutdown -r"
- UseGCOverheadLimit是一项策略,用于限制在抛出OutOfMemory错误之前,VM在GC中花费的时间比例
32/64位
在同时安装了32位和64位软件包的OS环境中,JVM会自动选择32位环境软件包。
如果要手动将环境设置为64位,可以使用以下参数进行设置:
-d<OS bit>
OS位可以是32或64。有关此的更多信息,请参见此处。
其他
- -server:启用“服务器Hotspot VM”;默认情况下,此参数在64位JVM中使用
- -XX:+UseStringDeduplication: Java 8u20引入了此JVM参数,以通过创建太多相同String的实例来减少不必要的内存使用。这通过将重复的String值减少为单个全局char []数组来优化堆内存
- -XX:+UseLWPSynchronization:设置基于LWP(轻量级进程)的同步策略,而不是基于线程的同步
- -XX:LargePageSizeInBytes:设置用于Java堆的大页面大小;它采用GB / MB / KB作为参数;页面大小较大时,我们可以更好地利用虚拟内存硬件资源;但是,这可能会导致PermGen的空间更大,从而迫使其减小Java堆空间的大小。
- -XX:MaxHeapFreeRatio:设置GC之后释放堆的最大百分比,以避免收缩。
- -XX:MinHeapFreeRatio:设置GC之后释放堆的最小百分比以避免扩展;要监视堆使用情况,可以使用JDK附带的VisualVM。
- -XX:SurvivorRatio:eden/survivor空间大小之比 -– 例如, -XX:SurvivorRatio=6 将每个survivor空间与eden空间之比设置为1:6,
- -XX:+UseLargePages:如果系统支持,则使用大页面内存;请注意,如果使用此JVM参数, OpenJDK 7倾向于崩溃
- -XX:+UseStringCache:启用字符串池中可用的常用分配字符串的缓存
- -XX:+UseCompressedStrings:对可使用纯ASCII格式表示的String对象使用byte []类型
- -XX:+OptimizeStringConcat:尽可能优化String连联操作
总结
在这篇简短的文章中,我们了解了一些重要的JVM参数 – 可用于调整和改善常规应用程序性能。
其中一些也可以用于调试目的。
如果您想更详细地探索参考参数,可以从这里开始。