目录
内存参数设置
垃圾收集
内存溢出
其他杂项
总结
java虚拟机(JVM)的启动参数可以用来调整其行为、性能和资源分配。以下是一些常见的JVM启动参数:
内存参数设置
初始化堆内存以满足应用程序需求是最常见的与性能相关的实践之一。
这就是为什么我们应该指定最小和最大堆大小。我们可以使用以下参数来实现这一点:
-Xms<heap size>[unit]
-Xmx<heap size>[unit]
在这里,单位表示我们将初始化内存的单位(由堆大小表示)。我们可以将单位标记为‘g’表示GB,‘m’表示MB,‘k’表示KB。
例如,如果我们想要分配最小的2GB和最大的5GB给JVM,我们需要写:
-Xms2G -Xmx5G
从Java 8开始,元数据空间(Metaspace)的大小不再固定。一旦达到全局限制,JVM会自动增加其大小。然而,为了克服任何不必要的不稳定性,我们可以使用以下方式设置Metaspace大小:
-XX:MaxMetaspaceSize=<metaspace size>[unit]
在这里,元空间大小表示我们想要分配给元空间的内存量。
根据Oracle的指南,除了总可用内存之外,第二个最具影响力的因素是为年轻代保留的堆的比例。默认情况下,YG的最小大小为1310 MB,最大大小为无限制。
我们可以显式地为它们分配:
-XX:NewSize=<young size>[unit]
-XX:MaxNewSize=<young size>[unit]
垃圾收集
为了提高应用程序的稳定性,选择正确的垃圾收集算法至关重要。
JVM有四种类型的GC实现:
串行垃圾收集器(Serial Garbage Collector)
并行垃圾收集器(Parallel Garbage Collector)
CMS垃圾收集器(CMS Garbage Collector)
G1垃圾收集器(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、s4lj等。NumberOfGCLogFiles参数表示单个应用程序生命周期内可以写入的最大日志文件数。GCLogFileSize参数指定文件的最大大小。最后,loggc指定了日志文件的位置。
在这里要注意的一点是,还有两个JVM参数可用(-XX:+PrintGCTimeStamps和-XX:+PrintGCDateStamps),我们可以使用它们在GC日志中打印日期时间戳。
例如,如果我们想要分配最多100个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表示文件将被写入的路径。可以给出任何文件名;但是,如果在名称中找到<pid>标记,当前进程导致内存不足错误的进程ID将附加到文件名中,并使用.hprof格式。
- OnOutOfMemoryError用于在发生内存不足错误时执行紧急命令。我们应该在cmd args的空间中使用适当的命令。例如,如果我们希望在发生内存不足时立即重启服务器,可以设置参数:
-XX:OnOutOfMemoryError="shutdown -r"
-
UseGCOverheadLimit是一个策略,它限制了在抛出OutOfMemory错误之前VM在GC中花费的时间的比例。
32/64 Bit
在安装了32位和64位软件包的操作系统环境中,JVM会自动选择32位的环境软件包。
如果我们想要手动将环境设置为64位,可以使用以下参数:
-d<OS位数>
其中,OS位数可以是32或64。我们可以在这里找到更多关于此的信息。
其他杂项
- -server:启用“Server Hotspot VM”。在64位JVM中,我们默认使用此参数。
- -XX:+UseStringDeduplication:Java 8u20引入了这个JVM参数,用于通过创建太多相同字符串的实例来减少内存的不必要使用。这通过将重复的字符串值减少到一个全局char[]数组来优化堆内存。
- -XX:+UseLWPSynchronization:设置基于LWP(轻量级进程)的同步策略,而不是基于线程的同步。
- -XX:LargePageSizeInBytes:设置用于Java堆的大页大小。它以GB/MB/KB为参数。使用较大的页面大小,我们可以更好地利用虚拟内存硬件资源;但是,这可能会导致PermGen的空间大小更大,从而迫使我们减小Java堆空间的大小。
- -XX:MaxHeapFreeRatio:设置GC后堆空闲的最大百分比,以避免收缩。
- -XX:MinHeapFreeRatio:设置GC后堆空闲的最小百分比,以避免扩展。为了监视堆使用情况,我们可以使用JDK附带的VisualVM。
- -XX:SurvivorRatio:Eden区/幸存者空间大小的比率。例如,-XX:SurvivorRatio=6将每个幸存者空间和Eden空间之间的比率设置为1:6。
- -XX:+UseLargePages:如果系统支持,则使用大页内存。请注意,OpenJDK 7在使用此JVM参数时可能会崩溃。
- -XX:+UseStringCache:启用String池中常用字符串的缓存。
- -XX:+UseCompressedStrings:对可以表示为纯ASCII格式的String对象使用byte[]类型。
- -XX:+OptimizeStringConcat:在可能的情况下优化字符串连接操作。
总结
在本文中,我们学习了一些重要的JVM参数,这些参数可以用来调整和改善一般应用程序的性能。我们也可以将其中一些用于调试目的。