堆错误是症状
OutOfMemoryError: Java heap space 表示分配失败,而不是堆参数一定设错。存活对象可能泄漏,也可能确实大于配置上限。先从堆转储和 GC 日志入手;猜测 -Xmx 既浪费时间又可能掩盖原因。
java -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp -Xmx512m -jar app.jar
泄漏还是容量不足
如果 full GC 反复只能回收很少对象,老年代仍居高不下,说明存活对象在增长。用堆转储找到支配树和引用链。如果存活集稳定且接近上限,可能是堆太小;扩容前先测量 GC 后的存活集。
容器限制
容器中的 JVM 必须考虑堆、metaspace、code cache、线程栈和本地内存。512 MB 容器配 -Xmx512m 没有给其他部分留空间,会被 OOM kill。容器限制应高于 JVM 总占用并留出余量。
验证平台期
运行一次长于原故障窗口的负载测试,同时启用转储和 GC 日志。修复泄漏后曲线会出现平台期;堆太小时会贴近新上限但不会无限攀升。要检查容器内存,而不只是堆。