You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在应用服务器中统计Java HeapSpace异常指标?

解决Payara环境下监控Java HeapSpace异常次数的方案

方法一:用Java Agent字节码增强统计异常次数

直接通过字节码修改java.lang.OutOfMemoryError的构造逻辑,统计HeapSpace类型的OOM次数,还能把计数器暴露给Prometheus或者JMX:

  • 写个简单的Java Agent,用ByteBuddy或ASM这类工具,在OOM的构造方法里插入计数逻辑,过滤出Java heap space相关的异常
  • 核心代码示例(用ByteBuddy):
    public class OOMCounterAgent {
        public static void premain(String agentArgs, Instrumentation inst) {
            inst.addTransformer((loader, className, classBeingRedefined, protectionDomain, classfileBuffer) -> {
                if ("java/lang/OutOfMemoryError".equals(className)) {
                    return new ByteBuddy()
                            .redefine(OutOfMemoryError.class)
                            .constructor(ElementMatchers.any())
                            .intercept(MethodDelegation.to(OOMInterceptor.class).andThen(SuperMethodCall.INSTANCE))
                            .make()
                            .getBytes();
                }
                return classfileBuffer;
            });
        }
    }
    
    public class OOMInterceptor {
        private static final AtomicLong heapOOMCount = new AtomicLong(0);
    
        public static void intercept() {
            // 通过栈回溯判断是否是HeapSpace OOM
            for (StackTraceElement elem : new Throwable().getStackTrace()) {
                if (elem.getClassName().contains("HeapSpace")) {
                    heapOOMCount.incrementAndGet();
                    break;
                }
            }
        }
    
        // 暴露成JMX MBean,让Prometheus JMX Exporter抓取,或者直接推指标
        public static long getHeapOOMCount() {
            return heapOOMCount.get();
        }
    }
    
  • 把Agent打包成jar,在Payara启动参数里加-javaagent:/path/to/your-agent.jar,之后就能通过JMX或者自定义的Prometheus指标接口拿到计数

方法二:监控Payara日志统计次数

旧版本Payara发生HeapSpace OOM时,会把异常信息写到domain/logs/server.log里,直接监控日志计数:

  • 用脚本或者日志工具(比如Promtail)抓取日志里包含java.lang.OutOfMemoryError: Java heap space的行数
  • 示例shell脚本(可以用cron定时执行推到Prometheus Pushgateway):
    #!/bin/bash
    LOG_PATH="/opt/payara/domain/logs/server.log"
    OOM_COUNT=$(grep -c "java.lang.OutOfMemoryError: Java heap space" $LOG_PATH)
    curl -X POST -H "Content-Type: text/plain" --data-binary "payara_heap_oom_total $OOM_COUNT" http://pushgateway:9091/metrics/job/payara_log_monitor
    
  • 这种方法简单直接,不需要修改代码,适合快速落地

方法三:用JVM Flight Recorder(JFR)抓OOM事件

如果你的旧版本Payara支持JFR(部分版本默认带),可以通过JFR记录OOM事件:

  • 启动Payara时加参数:-XX:+UnlockCommercialFeatures -XX:+FlightRecorder -XX:StartFlightRecording=duration=24h,filename=payara_oom.jfr
  • 可以用JFR的API实时解析事件计数,或者事后分析JFR文件提取OOM次数,再把计数转成Prometheus指标

方法四:Web应用全局Filter补充统计

如果你的业务都是Web请求,可以写全局Servlet Filter捕获请求链路中的HeapSpace OOM:

  • 示例Filter代码:
    @WebFilter("/*")
    public class OOMMonitorFilter implements Filter {
        private static final AtomicLong heapOOMCount = new AtomicLong(0);
    
        @Override
        public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
            try {
                chain.doFilter(req, res);
            } catch (OutOfMemoryError oom) {
                if (oom.getMessage() != null && oom.getMessage().contains("Java heap space")) {
                    heapOOMCount.incrementAndGet();
                }
                throw oom; // 不要吞异常,保证应用正常处理
            }
        }
    
        // 暴露JMX或Prometheus指标
        public static long getHeapOOMCount() {
            return heapOOMCount.get();
        }
    }
    
  • 注意:这个方法只能捕获Web请求里的OOM,后台线程(比如定时任务)的OOM抓不到,适合作为补充方案

内容的提问来源于stack exchange,提问作者Gui13

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 18:35:14