JMeter测试1万+用户遇OutOfMemoryError:根因排查与内存扩容咨询
JMeter高并发测试内存溢出问题排查
测试流程
- 先发送1个
POST请求 - 再发送N个
PUT请求(N为用户数量) - 所有响应保存至
target目录
问题现象
当测试用户量达到10000+时,JMeter抛出内存溢出错误:
Uncaught Exception java.lang.OutOfMemoryError: Java heap space in thread Thread[MyCoolTest 1-3165,5,main]. See log file for details.
运行一段时间后出现内存耗尽,日志详情如下:
java.lang.OutOfMemoryError: Java heap space at java.nio.HeapByteBuffer.<init>(HeapByteBuffer.java:61) ~[?:?] at java.nio.ByteBuffer.allocate(ByteBuffer.java:348) ~[?:?] at org.apache.logging.log4j.core.layout.StringBuilderEncoder.getThreadLocalState(StringBuilderEncoder.java:82) ~[log4j-core-2.13.1.jar:2.13.1] at org.apache.logging.log4j.core.layout.StringBuilderEncoder.encode(StringBuilderEncoder.java:64) ~[log4j-core-2.13.1.jar:2.13.1] at org.apache.logging.log4j.core.layout.StringBuilderEncoder.encode(StringBuilderEncoder.java:32) ~[log4j-core-2.13.1.jar:2.13.1] at org.apache.logging.log4j.core.layout.PatternLayout.encode(PatternLayout.java:231) ~[log4j-core-2.13.1.jar:2.13.1] at org.apache.logging.log4j.core.layout.PatternLayout.encode(PatternLayout.java:59) ~[log4j-core-2.13.1.jar:2.13.1] at org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender.directEncodeEvent(AbstractOutputStreamAppender.java:197) ~[log4j-core-2.13.1.jar:2.13.1] at org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender.tryAppend(AbstractOutputStreamAppender.java:190) ~[log4j-core-2.13.1.jar:2.13.1] at org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender.append(AbstractOutputStreamAppender.java:181) ~[log4j-core-2.13.1.jar:2.13.1] at org.apache.logging.log4j.core.config.AppenderControl.tryCallAppender(AppenderControl.java:156) ~[log4j-core-2.13.1.jar:2.13.1] at org.apache.logging.log4j.core.config.AppenderControl.callAppender0(AppenderControl.java:129) ~[log4j-core-2.13.1.jar:2.13.1] at org.apache.logging.log4j.core.config.AppenderControl.callAppenderPreventRecursion(AppenderControl.java:120) ~[log4j-core-2.13.1.jar:2.13.1] at org.apache.logging.log4j.core.config.AppenderControl.callAppender(AppenderControl.java:84) ~[log4j-core-2.13.1.jar:2.13.1] at org.apache.logging.log4j.core.config.LoggerConfig.callAppenders(LoggerConfig.java:543) ~[log4j-core-2.13.1.jar:2.13.1] at org.apache.logging.log4j.core.config.LoggerConfig.processLogEvent(LoggerConfig.java:502) ~[log4j-core-2.13.1.jar:2.13.1] at org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:485) ~[log4j-core-2.13.1.jar:2.13.1] at org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:460) ~[log4j-core-2.13.1.jar:2.13.1] at org.apache.logging.log4j.core.config.AwaitCompletionReliabilityStrategy.log(AwaitCompletionReliabilityStrategy.java:82) ~[log4j-core-2.13.1.jar:2.13.1] at org.apache.logging.log4j.core.Logger.log(Logger.java:161) ~[log4j-core-2.13.1.jar:2.13.1] at org.apache.logging.log4j.spi.AbstractLogger.tryLogMessage(AbstractLogger.java:2198) ~[log4j-api-2.13.1.jar:2.13.1] at org.apache.logging.log4j.spi.AbstractLogger.logMessageTrackRecursion(AbstractLogger.java:2152) ~[log4j-api-2.13.1.jar:2.13.1] at org.apache.logging.log4j.spi.AbstractLogger.logMessageSafely(AbstractLogger.java:2135) ~[log4j-api-2.13.1.jar:2.13.1] at org.apache.logging.log4j.spi.AbstractLogger.logMessage(AbstractLogger.java:2028) ~[log4j-api-2.13.1.jar:2.13.1] at org.apache.logging.log4j.spi.AbstractLogger.logIfEnabled(AbstractLogger.java:1899) ~[log4j-api-2.13.1.jar:2.13.1] at org.apache.logging.slf4j.Log4jLogger.info(Log4jLogger.java:184) ~[log4j-slf4j-impl-2.13.1.jar:2.13.1] at org.apache.jmeter.threads.JMeterThread.initRun(JMeterThread.java:712) ~[ApacheJMeter_core-5.3.jar:5.3] at org.apache.jmeter.threads.JMeterThread.run(JMeterThread.java:252) ~[ApacheJMeter_core-5.3.jar:5.3] at java.lang.Thread.run(Thread.java:829) [?:?]
环境信息
- 运行环境:CircleCI的Linux机器,Ubuntu 20.04.5 LTS,x86_64架构
- Java版本:openjdk:11.0
- JMeter版本:5.5
- 依赖管理:通过Maven在Docker镜像中安装JMeter
咨询问题
- 该问题的根本原因是什么?
- 在CircleCI的Docker镜像中运行JMeter时,是否可以增加内存?(推测可找到
jmeter.bat文件并调大Xmx参数)
解答
问题1:根本原因分析
从日志和测试场景来看,核心原因包括:
- 默认堆内存不足:JMeter默认分配的Java堆内存(通常几百MB)无法支撑10000+并发线程,每个线程需要存储请求/响应数据、上下文状态等,线程数过载直接导致内存耗尽。
- 响应保存加剧内存消耗:将所有响应保存到
target目录的操作,如果未配置异步写入或批量处理,会在内存中暂存大量响应数据,进一步占用堆空间。 - 日志系统内存压力:溢出发生在Log4j编码阶段,高并发下大量INFO级别日志输出会持续占用内存,频繁的日志生成和编码操作加速了内存耗尽。
问题2:CircleCI Docker镜像中调整JMeter内存的方法
可以增加内存,注意Linux环境下没有jmeter.bat,对应是jmeter shell脚本,常用调整方式如下:
- 修改启动脚本:找到Docker镜像中
/opt/apache-jmeter/bin/jmeter脚本,修改JVM_ARGS参数,比如将-Xmx1g改为-Xmx4g(建议不超过物理内存的70%)。 - 环境变量传递:在CircleCI配置文件(
.circleci/config.yml)中启动JMeter时设置环境变量:JVM_ARGS="-Xms2g -Xmx4g" jmeter -n -t testplan.jmx -l result.jtl - Maven插件配置:如果通过Maven运行JMeter,在
pom.xml中添加JVM参数配置:<plugin> <groupId>com.lazerycode.jmeter</groupId> <artifactId>jmeter-maven-plugin</artifactId> <version>3.5.0</version> <configuration> <jvmArgs>-Xms2g -Xmx4g</jvmArgs> <!-- 其他测试配置 --> </configuration> </plugin>
额外优化建议:
- 关闭不必要的监听器,仅保留核心结果收集组件
- 降低日志级别至WARN或ERROR,减少日志输出量
- 配置响应异步写入,避免内存堆积大量响应数据
- 采用分布式测试,将并发压力分散到多个JMeter节点
内容的提问来源于stack exchange,提问作者Zedd Demir
相关产品推荐
相关产品推荐

