Spring Boot并发OOM问题:分配16GB内存仅用6GB仍报错
压测时Tomcat Java堆内存溢出问题排查与解决
问题场景
调用基于Elasticsearch的REST API时,使用Apache ab压测出现以下错误:
"http-nio-8080-exec-3" java.lang.OutOfMemoryError: Java heap space
相关命令
- 压测命令:
ab -n 20 -n 1000 "localhost:8080/getData" - 应用启动命令:
nohup java -Xms 2g -Xmx 16g server.jar
异常现象
- 已配置
-Xms2g -Xmx16g,但Java进程仅占用6-8GB内存; - 压测时触发OOM错误,部分场景下无报错直接崩溃;
- 启动多实例加负载均衡无法解决问题。
错误栈信息
java.lang.OutOfMemoryError: Java heap space at org.apache.coyote.http11.Http11OutputBuffer.<init>(Http11OutputBuffer.java:126) at org.apache.coyote.http11.Http11Processor.<init>(Http11Processor.java:238) at org.apache.coyote.http11.AbstractHttp11Protocol.createProcessor(AbstractHttp11Protocol.java:636) at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:771) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1425) at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:748) java.lang.OutOfMemoryError: Java heap space at org.apache.coyote.http11.Http11OutputBuffer.<init>(Http11OutputBuffer.java:126) at org.apache.coyote.http11.Http11Processor.<init>(Http11Processor.java:238) at org.apache.coyote.http11.AbstractHttp11Protocol.createProcessor(AbstractHttp11Protocol.java:636) at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:771) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1425) at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:748) Exception in thread "http-nio-8080-exec-2" Exception in thread "http-nio-8080-exec-3" java.lang.OutOfMemoryError: Java heap space java.lang.OutOfMemoryError: Java heap space at org.apache.coyote.http11.Http11InputBuffer.init(Http11InputBuffer.java:717) at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:980) at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:785) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1425) at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:748) Exception in thread "http-nio-8080-exec-7" Exception in thread "http-nio-8080-exec-9" java.lang.OutOfMemoryError: Java heap space Exception in thread "http-nio-8080-exec-15" Exception in thread "http-nio-8080-exec-16" java.lang.OutOfMemoryError: Java heap space Exception in thread "http-nio-8080-exec-4" java.lang.OutOfMemoryError: Java heap space Exception in thread "http-nio-8080-exec-11" java.lang.OutOfMemoryError: Java heap space Exception in thread "http-nio-8080-exec-12" java.lang.OutOfMemoryError: Java heap space java.lang.OutOfMemoryError: Java heap space Exception in thread "http-nio-8080-exec-14" java.lang.OutOfMemoryError: Java heap space Exception in thread "http-nio-8080-exec-13" java.lang.OutOfMemoryError: Java heap space Exception in thread "http-nio-8080-exec-18" java.lang.OutOfMemoryError: Java heap space Exception in thread "http-nio-8080-exec-19" java.lang.OutOfMemoryError: Java heap space java.lang.OutOfMemoryError: Java heap space Exception in thread "http-nio-8080-exec-29" java.lang.OutOfMemoryError: Java heap space
问题分析
从错误栈可见,OOM发生在Tomcat的IO缓冲区(Http11OutputBuffer、Http11InputBuffer)初始化阶段,结合场景分析可能原因:
- 压测命令参数错误:
ab命令重复使用-n参数(正确应为-c指定并发数、-n指定总请求数),导致并发量异常,Tomcat为大量瞬时连接分配缓冲区,快速耗尽堆内存。 - JVM参数未生效:
-Xms、-Xmx与数值之间存在空格(正确格式为-Xms2g而非-Xms 2g),JVM会忽略该参数,使用默认堆大小(通常仅几百MB),直接引发OOM。 - Tomcat缓冲区配置过大:默认IO缓冲区参数(如HTTP头缓冲区、Socket缓冲区)偏大,高并发下每个连接占用内存累加后超出堆限制。
- ES查询内存泄漏:
getData接口的ES查询未做分页,返回超大结果集,或查询资源未及时释放,高并发下大对象堆积导致内存耗尽。
解决方案
修正压测命令
将错误的双-n参数改为-c(并发数)和-n(总请求数),示例:ab -c 20 -n 1000 "localhost:8080/getData"修复JVM启动参数
调整参数格式,确保堆内存配置生效,同时补充-jar参数(启动jar包必需):nohup java -Xms2g -Xmx16g -jar server.jar &优化Tomcat缓冲区与线程配置
在应用配置文件(如application.properties)中添加以下参数:# 减小HTTP头缓冲区大小 server.tomcat.max-http-header-size=8192 # 调整Socket缓冲区大小 server.tomcat.socket-buffer-size=8192 # 限制工作线程数,避免过多线程占用内存 server.tomcat.max-threads=200 # 限制最大连接数 server.tomcat.max-connections=1000优化ES查询逻辑
- 对ES查询做分页处理,限制单次返回数据量,示例:
SearchRequest searchRequest = new SearchRequest("index_name"); SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); sourceBuilder.from(0); sourceBuilder.size(100); // 单次返回100条数据 searchRequest.source(sourceBuilder); - 确保ES客户端资源及时关闭,避免连接和结果对象泄漏。
- 对ES查询做分页处理,限制单次返回数据量,示例:
生成堆转储分析内存泄漏
在启动命令中添加堆转储参数,OOM时自动生成内存快照,后续用MAT等工具分析:nohup java -Xms2g -Xmx16g -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/heapdump.hprof -jar server.jar &
内容的提问来源于stack exchange,提问作者Prakitidev Verma
相关产品推荐
相关产品推荐

