“内存不足就把内存调大”是开服圈最常见的一句话,也是最容易把服务器调崩的一句话。手机上的内存和电脑不一样:服务端只是众多应用之一,给它的堆内存越多,Android 可用于系统和其他应用的内存就越少,最后可能是系统先把整个 Minexa 杀掉,而不是服务端报一个漂亮的 OutOfMemoryError。
更常见的现场是这样的:4 GB 的手机,你照着某篇 PC 教程把上限填成 4096,服务端起先跑得好好的,二十分钟后有人跑图,整台手机一卡,几秒后 Minexa 从后台消失,日志里连一行红字都没有。
这一页讲清楚四件事:-Xmx 到底是什么、你的手机该给多少、改在哪里、以及内存出问题时怎么判断是 OOM 还是被系统杀了。
「JVM 内存上限」默认 1024 MB,可填 256~65536 MB,改完要重启才生效。
通用红线:不要超过设备可用 RAM 的 60%;4 GB 给 1024~1536 MB,6 GB 给 1536~2048 MB,8 GB 给 2048~3072 MB。
给太大:系统低内存杀手直接杀进程,通常没有任何 Java 报错。
给太小:GC 频繁、TPS 抖动,严重时报
OutOfMemoryError: Java heap space。
三个“内存”不是一回事#
新手最容易混的就是这三个数,先分开:
| 名词 | 是什么 | 在哪看 |
|---|---|---|
| 手机物理内存 | 手机总共的 RAM,比如 8 GB | 设置 → 关于手机 |
| 应用/进程占用 | Minexa 和服务端实际占用的内存(RSS) | 概览 Hero 的「内存」条、系统开发者选项 |
| JVM 堆内存 | Java 服务端能用来放对象的内存,由 -Xmx 限制 | 启动设置里的「JVM 内存上限」 |
Minexa 里的「内存」条显示的是服务端进程实际占用 / -Xmx 上限。未运行时显示 -- / 上限。它不等于手机剩余内存,也不等于堆内存使用率 —— 内存条没满,不代表手机内存宽裕。
Minexa 启动 Java 服务端时只显式设置最大堆(-Xmx),没有设置初始堆(-Xms),也没有 PC 圈流行的 Aikar Flags。JVM 会按需从较小的堆开始增长,直到上限。所以你不需要、也没法在应用里填 -Xms。
为什么“给大一点”反而会崩#
Android 有一个低内存杀手(LMK):当系统内存紧张时,它会按优先级杀进程。前台服务能提高存活优先级,但不能让系统无限容忍。
给服务端 4096 MB 的结果可能是:
服务端刚开始只用 800 MB,看起来没事;
玩家跑图、生成区块,堆涨到 3 GB;
手机总内存 4 GB,系统和其他应用也要用,剩余内存不足;
LMK 直接杀掉 Minexa(可能连崩溃日志都来不及写);
你看到的是“服务器突然消失”,而不是 OOM。
所以那句红线要这么理解:堆上限不是“服务端能用的内存”,而是“服务端最多能占的内存”。填 4096,就是允许它在最需要内存的时候把整机 4 GB 抢走。目标是够用且留有余量,不是越大越安全。
为什么卡在 60%?因为服务端涨到上限的那一刻,系统、桌面、聊天软件和相册缓存还要同时活着。留下 40%,就是给那一秒的整机留一条退路。8 GB 手机按这个算法上限是 4.8 GB,但实际建议 3 GB 左右,剩下的余量留给发热降频时的抖动。
按设备和人数给推荐值#
下面给的是经验区间,适用于原版/Paper + 少量插件。模组服、大型整合包、预生成地图要在此基础上加。
| 手机内存 | 建议人数 | JVM 内存上限 | 说明 |
|---|---|---|---|
| 3 GB | 1~2 人 | 768~1024 MB | 别开大型插件,后台尽量清空 |
| 4 GB | 2~3 人 | 1024~1536 MB | 最常见的新手配置,先用 1024 跑一晚 |
| 6 GB | 3~5 人 | 1536~2048 MB | 留 1 GB 以上给系统 |
| 8 GB | 5~10 人 | 2048~3072 MB | 建议配合预生成 |
| 12 GB 以上 | 10 人以上 | 3072~4096 MB | 瓶颈通常在 CPU 和散热 |
在原版基础上,玩法越重,给的越多,但别一次到位:
Paper + 五六个常用插件:按上表取中间值,比如 4 GB 手机给 1280 MB。
模组服(Forge / NeoForge / Fabric 整合包):在上表基础上加 512~1024 MB,同时把视距降到 6。
预生成过的大世界:加 256~512 MB,因为磁盘上区块多,读取时对象也多。
网上很多教程默认你是 8 GB 以上的 PC。4 GB 手机给 4096 MB,服务端还没加载完,系统就可能把它杀了。先给 1024 MB 跑起来,观察概览的内存条和 TPS,再小幅上调。
怎么改:启动抽屉里的「JVM 内存上限」#
回概览,点齿轮:找到「启动服务端」卡,点它右上角的齿轮,打开「服务器启动设置」抽屉。
确认运行环境和 Java 版本:这项和内存无关,但选错会直接启动失败,顺手核对一遍,名词解释见 运行环境管理。
找到「JVM 内存上限」:输入框里填整数,单位 MB,只接受 256~65536 之间的值。看不懂范围就记住:1024 是默认值。
点「完成」,然后停止再启动:
-Xmx是 JVM 的启动参数,运行中改不了,必须重启。应用没有独立重启按钮,先「停止」再「启动」。
成功标志:服务端跑起来后,概览的「内存」条显示 xxx MB / 你填的上限。如果上限没变,说明抽屉没保存成功,或者你只是停止后切了配置却没重启。
内存调整的影响不是线性的。每次加 256 MB,跑一个晚上或一次多人游戏,再决定要不要继续加。一次从 1024 跳到 4096,出问题了你不知道是哪一步导致的。
给太小会怎样:GC 和 OutOfMemoryError#
堆给得太小的第一反应不是崩,而是卡。堆快满时,JVM 会频繁做垃圾回收(GC,把没人用的对象清掉腾地方),每次回收都要暂停一部分工作,每刻耗时跟着抖动,TPS 就一阵一阵地掉。
三个能看到的迹象:
概览内存条长期在 90% 以上,怎么玩都不下降;
TPS 忽高忽低,而不是稳定偏低;
日志里出现
GC overhead limit exceeded(回收花了太多时间却没腾出空间)。
再严重一点就报错了:OutOfMemoryError: Java heap space,堆真的用完。处理顺序是这样的:
确认上限是不是明显低于推荐值(比如 8 GB 手机还在用 512 MB);
降视距和模拟距离,清掉落物和实体;
检查最近新装的插件/模组,尤其是会缓存区块和实体的那种;
前面三步做完还是反复 OOM,再往上加 256~512 MB。
OOM 和“被系统杀掉”怎么区分#
这两种都表现为“服务器没了”,但原因完全相反,处理方式也相反:一个是内存给少了,一个是给多了。
| 对比项 | JVM 的 OOM | 被系统低内存杀手杀掉 |
|---|---|---|
| 有没有 Java 报错 | 有,java.lang.OutOfMemoryError | 通常没有,日志停在正常输出 |
logs/latest.log 末尾 | 有异常堆栈和一堆 at … 行 | 没有任何收尾,直接断掉 |
| 什么时候发生 | 加载世界、装模组、区块暴涨时 | 后台待久了、锁屏后、开了相机或大型游戏 |
| 先做什么 | 降视距、查模组、加 256~512 MB | 降上限、关省电限制、加电池白名单 |
判断动作只有两下:打开 logs/latest.log 看最后 30 行有没有 OutOfMemoryError;再看崩溃报告里有没有 Java 异常。有 → 是 OOM;一条都没有、只看到进程凭空消失 → 更像被杀。
被杀那条路要往系统侧查:手机电池优化、后台限制、锁屏清理。做法见 后台保活,日志和崩溃报告的读法见 崩溃与存档损坏。
内存不是唯一瓶颈#
TPS 低不一定是内存小。CPU 单核性能、区块生成、实体数量、磁盘写入、手机降频都会拖慢服务端。一个内存充足但 CPU 被红石/漏斗/刷怪塔占满的服,TPS 一样会掉。
判断方法:内存条没满、TPS 却低 → 优先看 CPU 和实体;内存条长期满、频繁 GC → 才考虑内存。两边的指标关系在 TPS 与 MSPT 里,具体的排查动作在 内存不足与 CPU 占用 里。
概览「内存」条显示的上限,和你在抽屉里填的数字一致。
连着玩 30 分钟,内存条没有一直贴在 100%。
你说得出自己手机的标称内存,以及 60% 对应多少 MB。
最近一次 OOM,你在
logs/latest.log末尾看到过OutOfMemoryError。进程消失但日志没有报错时,你知道要去查电池优化而不是加内存。
下一步#
把视距一起降下来:视距与模拟距离
系统优化清单:综合优化
已经 OOM 了:内存不足与 CPU 占用