规则引擎服务跑六小时后报 OutOfMemoryError: Metaspace,jstat -gc 的 MU 列从 180MB 涨到 512MB,MC 正好卡在上限。第一次遇到会往复杂处想,其实漏掉的多是个小前提。

jstat -gc 21455 5000 20
jcmd 21455 GC.class_stats | sort -k3 -nr | head -20
java -XX:MaxMetaspaceSize=1g -Xlog:class+load=info -jar rule.jar

每条规则用 Groovy 或字节码库生成一个新类,类加载后又被静态 Map 持有,旧类永远不卸载。MaxMetaspaceSize 设了 512m,到顶就抛 OOM。这一点先确认清楚,后面就不用反复试。

「Metaspace 溢出」相关的日志我一般连着看前后五分钟,单看一条报错经常判断不出是哪一步失败。新版本先放一台机器上跑一天再全量,问题一般在这段时间暴露。

备份不是备了就行,恢复一次才算数,很多备份文件打开才发现是空的。接口问题先分清是没发出去、发出去了没收到,还是收到了处理失败。

偶发问题先统计频率,一小时几次和一天一次,查法完全不同。

具体做法是,先看 MC 和 MU 是否持续上涨 确认是类泄漏不是容量不够;把生成的类改成脚本缓存 按规则 id 复用;卸载不再使用的 ClassLoader 并清掉静态引用;临时调大 MaxMetaspaceSize 只用于争取排查时间。

改完照着核一遍,MU 稳定在 300MB 以内 连续跑一天不再出现 Metaspace 的 OOM。

作者 9823189