Minecraft 服务端 JVM 调优指南(低资源 / 非专用服务器专用)
写在前面
这份文档专门针对资源非常有限的 Minecraft 服务端(典型配置:2核4G、4核8G VPS/独立小服务器、甚至更低的共享主机),目标是:在内存紧张、CPU 核心数不多的情况下,尽可能让服务器 TPS 稳定、长尾延迟可控,避免频繁卡顿或被系统杀掉。
适用前提:
- 服务器不是高配专用物理机或云大内存实例(8核16G+、甚至更高)
- Java 版本最好是 Java 25,至少是 java21
这份调优的核心思路是:
- 极致放大 Eden + 快速晋升老年代(压缩 Survivor + 极低 TenuringThreshold)
- 非常激进的并发标记启动阈值(IHOP 15--20)
- 更积极的 Mixed GC(降低活对象阈值、增加混合回收次数)
- 非专用机必须考虑内存归还(SoftMax + 周期性 GC + 激进收缩)
这些改动在小堆、低核环境下能显著降低 50--200ms 级别的长尾停顿,让 tick 更稳定,但也会牺牲一部分 GC 吞吐和平均性能------这正是低资源 MC 必须做的取舍。
这份配置不适合高配服务器。如果服务器有 8G+ 内存、多核 CPU,直接用 ZGC 默认配置通常更好,没必要在 G1 上抠这么多参数
G1GC 配置(推荐用于 2G+ 内存)
文档参数基于 Java 25,java21 去掉 UseCompactObjectHeaders 即可
非专用服务器
bash
#!/bin/bash
java -Xms512M \
-Xmx2500M \
-XX:SoftMaxHeapSize=1500M \
-XX:+UseG1GC \
-XX:MaxGCPauseMillis=200 \
-XX:G1ReservePercent=20 \
-XX:G1MixedGCCountTarget=4 \
-XX:+DisableExplicitGC \
-XX:+UseStringDeduplication \
-XX:+UseCompactObjectHeaders \
-XX:G1PeriodicGCInterval=60000 \
-XX:MaxHeapFreeRatio=30 \
-XX:MinHeapFreeRatio=10 \
-XX:-ShrinkHeapInSteps \
-XX:SurvivorRatio=32 \
-XX:MaxTenuringThreshold=1 \
-XX:InitiatingHeapOccupancyPercent=20 \
-XX:+UnlockExperimentalVMOptions \
-XX:G1NewSizePercent=30 \
-XX:G1MaxNewSizePercent=40 \
-jar java.jar
mc 专用服务器
bash
#!/bin/bash
java -Xms2500M \
-Xmx2500M \
-XX:+AlwaysPreTouch \
-XX:+UseG1GC \
-XX:MaxGCPauseMillis=200 \
-XX:G1ReservePercent=20 \
-XX:G1MixedGCCountTarget=4 \
-XX:+DisableExplicitGC \
-XX:+UseStringDeduplication \
-XX:+UseCompactObjectHeaders \
-XX:SurvivorRatio=32 \
-XX:MaxTenuringThreshold=1 \
-XX:InitiatingHeapOccupancyPercent=20 \
-XX:+UnlockExperimentalVMOptions \
-XX:G1NewSizePercent=30 \
-XX:G1MaxNewSizePercent=40 \
-jar java.jar
Serial GC 配置(适用于极小内存)
对于 1G 左右的堆内存,Serial GC 比 G1 更合适,因为堆不大停顿时间几乎没有区别
不过这个堆大小运行 mc 稍微有点吃力了
bash
#!/bin/bash
java \
-Xms1000M \
-Xmx1000M \
-XX:+UseSerialGC \
-XX:+UseCompactObjectHeaders \
-XX:NewRatio=1 \
-XX:SurvivorRatio=32 \
-jar java.jar
调优详解
调优目标
以 2核4g 的机器为例
MC 是 java 应用里极其少见的大型实时游戏服务端,对象分配速率非常高,同时又要求 tick 稳定、长尾延迟尽量低。在资源受限的前提下,首要目标是控制内存占用,其次是压低延迟抖动。
GC 选择上,堆不大、核心数也不多。Parallel GC 在小堆下虽然吞吐不错,但停顿不可预测,而且并行度在 2 核机器上发挥空间有限;Serial GC 停顿过长,不适合实时场景。MC 主线程基本吃满一个核心,反而给并发 GC 留出了一定余量,因此用 G1 在这个场景下更容易在延迟和资源之间取得平衡。ZGC 从模型上看确实很契合"高分配速率 + 低延迟"的特征,但在 2~3G 级别的小堆上收益有限,额外的元数据开销和并发成本反而不划算。
对象生命周期结构上,MC 和典型 Web 应用差异明显。普通后端应用通常是"极短命对象占大头,真正长寿对象数量少但存活时间很长,接近常驻"。而 MC 是:短命对象很多,真正常驻的对象反而不多,中间夹着大量"中等寿命对象"------可能存活几十秒到几十分钟。从 GC 视角看,这些已经属于长寿对象,但在业务层面并不是常驻。
在 G1 默认策略下,这些中等寿命对象会在 Survivor 区多次复制,增加 Young GC 的停顿时间;等它们陆续晋升到老年代后,如果并发标记和 Mixed GC 的节奏偏保守,又会出现老年代回收跟不上对象自然死亡节奏的问题,导致老年代占用上升、Mixed 次数增加,甚至触发更重的停顿。
因此调优思路的核心是:放大 Eden,尽量压缩 Survivor,让对象尽快结束在年轻代内部的反复搬运;同时降低 IHOP 等阈值,让并发标记更早开始,Mixed GC 更积极,保证老年代的清理速度能够跟上中等寿命对象的产生与死亡节奏。整体上是用更多 Eden 空间换更少的复制成本,再用更激进的老年代回收策略来维持堆的动态平衡,从而在有限内存下尽量压低长尾停顿。
GC 选择
指定 G1GC:
bash
-XX:+UseG1GC
内存优化
为了节省内存:
bash
-Xms512M # 初始内存
-Xmx2500M # 最大内存,防止 OOM
-XX:SoftMaxHeapSize=1500M # 软上限,防止服务器其他服务(尤其是某些需要占用一定内存的定时任务)运行时内存不足导致 MC 被杀
-XX:+UseCompactObjectHeaders # 开启压缩对象头,MC 有很多小对象,该参数预计可以省下 5% 左右的内存
-XX:+UseStringDeduplication # 开启重复字符串合并,MC 有很多相同的字符串
-XX:G1PeriodicGCInterval=60000 # 每 60 秒检测一次,如果 JVM 空闲就触发一次并发 GC 并归还内存
-XX:MaxHeapFreeRatio=30 # 堆缩容阈值
-XX:MinHeapFreeRatio=10 # 堆扩容阈值
-XX:-ShrinkHeapInSteps # 禁用分步缩容,堆空闲时一次性缩到位而非分多步缓慢收缩(内存归还更加积极)
注意上述参数为了让 java 服务积极归还内存是牺牲了一定的稳定性的,如果是专用服务器建议修改为
bash
-Xms2500M # 初始内存,保持和最大内存一致
-Xmx2500M # 最大内存,这个参数给元空间等非堆空间及系统保留了较高的余量,若内存占用长期稳定可考虑调大
-XX:+UseCompactObjectHeaders # 开启压缩对象头,MC 有很多小对象,该参数预计可以省下 5% 左右的内存
-XX:+UseStringDeduplication # 开启重复字符串合并,MC 有很多相同的字符串
-XX:+AlwaysPreTouch # 启动时初始化内存页,避免内存申请时抖动
延迟优化
为了稳定长尾延迟:
bash
-XX:MaxGCPauseMillis=200 # 最大暂停时间(理论上这个值在mc上应该为50以下,但是不要在低资源服务器强行降低这个值)专用服务器可以调小这个值到150-180
-XX:G1ReservePercent=20 # 预留 20% 的堆作为缓冲,MC 负载波动大需要较为激进的缓冲(默认 10%),为了避免内存浪费可以适当调小这个值
-XX:G1MixedGCCountTarget=4 # 混合回收次数,这里更多的是个经验值(默认 8)
-XX:+DisableExplicitGC # 禁止代码中调用 System.gc(),某些 mod 或插件代码写的不好
快速收敛优化
为了快速收敛(MC 负载恒定,设置如下参数可以使 G1 快速收敛到最佳状态):
bash
-XX:InitiatingHeapOccupancyPercent=20 # 并发标记阈值,MC 对象分配快且有很多"中等寿命"的对象,需要较为激进的并发标记阈值(默认 45)这在低cpu核心数时是最关键的 tradeoff 参数,过低会导致并发标记频繁抢占 CPU,核心多可以调小这个值到15左右
-XX:+UnlockExperimentalVMOptions # G1NewSizePercent G1MaxNewSizePercent 不是个正式特性,需要显式打开实验性参数
-XX:G1NewSizePercent=30 # 新生代最小大小,防止初始堆eden被击穿
-XX:G1MaxNewSizePercent=40 # 新生代最大大小,防止老年代被挤压
特殊调优
bash
-XX:SurvivorRatio=32 # Eden 与 Survivor 比例,Survivor会被很快晋升不需要太大
-XX:MaxTenuringThreshold=1 # Survivor晋升老年代阈值,确保Survivor不被反复复制