WireMock使用withBodyFile加载大文件时触发OutOfMemoryError问题
问题根因
你的API调用方式本身没有语法错误,触发OOM是WireMock默认机制的设计特性导致的:
- WireMock默认会开启响应日志留存能力,所有命中桩规则的请求,在响应返回给客户端后,框架会在收尾阶段把完整的响应内容加载到内存,生成
LoggedResponse对象留存,用于后续的请求校验、日志查询、管理面板展示等功能。 - 你使用
withBodyFile加载300MB以上大文件时,虽然向客户端返回响应的过程是流式读取磁盘文件输出,不会全量占内存,但到了日志记录环节,框架会调用Response.getBody()方法,把整个响应体的输入流全部读取为连续的byte[]字节数组存入堆内存。Java中字节数组需要占用连续的堆空间,300MB的文件加上堆内存本身的其他占用,很容易超出分配的堆内存上限,直接抛出堆内存不足的OutOfMemoryError。 - 这个问题和你用
withBodyFile没有直接关系,只要WireMock的响应日志留存功能开启,任何形式的大尺寸响应体都会触发全量读入内存的逻辑,WireMock本身的设计定位就不是承载百MB级以上大文件的Mock服务。
解决方式
你可以根据自己的场景选以下方案处理:
- 关闭响应日志留存能力:如果不需要WireMock记录历史请求/响应做校验,可以在启动配置里关闭响应日志,从根源上避免框架全量读取响应体。配置示例:
WireMockServer server = new WireMockServer( wireMockConfig() .port(8080) .disableResponseJournal() );
- 调大JVM堆内存:如果必须保留响应日志能力,可以把JVM最大堆内存调整到响应文件大小的1.5~2倍以上(比如300MB文件至少设置
-Xmx800m),但这个方案不推荐,大字节数组属于大对象,会频繁触发Full GC,高频调用场景下性能很差。 - 拆分Mock能力:不要用WireMock处理百MB级以上大文件的Mock,把这类请求转发给Nginx、本地静态HTTP服务这类原生支持流式返回、不会全量缓存响应体的工具处理,WireMock只负责普通业务接口的Mock,是稳定性最高的方案。
内容的提问来源于stack exchange,提问作者Dvir
相关产品推荐
相关产品推荐

