JVM参数设置入门案例与实战指南

JVM的内存参数繁多,但在实际应用中主要关注堆内存大小设置及堆内存中新生代和老年代的大小设置。下面将介绍一个简单的JVM启动参数设置案例。

-Xms -Xmx:-Xms 表示初始堆大小,-Xmx 表示最大堆大小。一般将 Xms 和 Xmx 设置为相同的值,避免垃圾回收后JVM重新分配堆内存大小而引起内存震荡,影响性能。

-XX:NewSize:-XX:NewSize=1g 表示设置新生代的大小为1GB,一般建议设置为总堆内存的1/3。

-XX:MetaspaceSize:表示元空间的大小为128MB,当要加载的类库过多时,可以适当调高这个值。

-XX:NewRatio:-XX:NewRatio=3 表示设置新生代与老年代的比值为1:3,因此新生代占整个堆栈的1/4,老年代占整个堆内存的3/4。

-XX:SurvivorRatio: -XX:SurvivorRatio=8 表示Eden区和两个Survivor区的比值为8:1,即Eden:SurvivorTo=8:1、Eden:SurvivorFrom=8:1。最终的结果是Eden:SurvivorTo:SurvivorFrom=8:1:1。

-XX:+UseParNewGC -XX:+UseConcMarkSweepGC:垃圾回收器设置,-XX:+UseParNewGC 表示设置年轻代垃圾回收器为ParNew垃圾回收器。-XX:+UseConcMarkSweepGC 表示设置老年代垃圾回收器为CMS垃圾回收器。

-OOM异常诊断设置: -XX:HeapDumpOnOutOfMemoryError 表示当发生OOM时转储堆到文件。-XX:HeapDumpPath 表示堆的转储文件路径地址。这两个参数结合起来,可以在程序出现OOM时及时将堆信息打印出来,方便后续分析故障。

在进行JVM参数设置时需要重点关注垃圾回收器的设置和JVM内存的设置。接下以在一个8GB的服务器上独立运行一个名为start.jar的Netty应用服务为例,介绍内存设置的流程:

  1. 预留操作系统内存:首先确定操作系统的总内存为8GB,为操作系统预留2GB内存,保障操作系统运行流畅,将剩余的6GB内存分配给应用程序。
  2. 确定直接内存:由于我们的应用程序为Netty服务端,Netty服务在运行过程中会使用直接内存来提高性能,因此应用程序在运行过程中会有大量直接内存的使用。为了保障应用程序既有足够的直接内存保障服务高效运行,又不至于占用过多堆外内存导致系统内存不足而产生OOM问题,我们将2GB(应用程序可用内存的1/3)内存预留给直接内存,通过 -XX:MaxDirectMemorySize-2g 设置可用的最大堆外内存为2GB。在使用过程中会按需分配足够的内存给直接内存,但最大不超过2GB。
  3. 确定Java堆的大小:剩余的4GB内存,将3GB分配给Java堆,这样就可以确定 -Xm3g -Xmx3g
  4. 确定新生代和老年代的大小:由于没有特殊的大对象和过多长生命周期的对象,所以可以将堆内存的1/3分配给新生代,也就是-XX:NewSize=1g,将其他剩余的2GB内存分配给老年代。同时,由于我们的程序为一般的Java程序,所以Survivor区和Eden区的配置可以采用官网建议的值,这里不做特殊设置。
  5. 确定元空间区:接下来还剩余1GB内存可供应用程序使用,由于应用程序及其依赖的JAR包不大,所以可通过 XX:MetaspaceSize=128m 设置元空间大小为128MB。将剩余的少部分内存留给操作系统或其他应用程序使用。
  6. 配置GC:最后设置垃圾回收器、OOM异常数据转储路径和GC日志。使用 -XX:+UserConcMarkSweepGC 可设置老年代使用CMS垃圾回收器,新生代使用默认的ParNew垃圾回收器。使用 -XX:+UseG1GC 可设置使用G1垃圾回收器。

具体配置如下:

java -server -XX:MaxDirectMemorySize=2g -Xms3g -Xmx3g -XX:NewSize=1g -XX:MetaspaceSize=128m -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -xx:+HeapDumponCutOfMemoryError -XX:HeapDumpPath=dump.log -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCDatestamps -XX:+PrintHeapAtGC -Xlogge:../gc/gc.log -jar start.jar

另外,需要注意不同JVM版本的配置参数不同,比如 -XX:PermSizeXX -XX:MaxPermsize 分别表示永久代的初始化大小和永久代的最大大小。但是在Java8已经没有永久代了,因此也不存在该配置参数。

标签:游戏攻略