运行JUnit时触发java.lang.OutOfMemoryError错误的排查与修复咨询
解决JUnit测试报告生成时的
java.lang.OutOfMemoryError: Requested array size exceeds VM limit问题 这个问题我之前也遇到过类似的情况,咱们先从栈跟踪和你的配置里找线索:这不是测试运行时堆内存不足的问题,而是在所有测试跑完、生成报告的阶段,Ant的JUnit报告格式化器试图生成一个超大字符串,转字节数组时请求的数组大小超出了JVM的限制(通常这个限制是数组长度不能接近Integer.MAX_VALUE,或者计算数组大小时发生了整数溢出)。
环境与错误详情
- Ant版本:1.9.4
- ANT_OPTS配置:
ANT_OPTS=-Xmx10G - JUnit任务配置:
<junit fork="yes" newenvironment="false" haltonfailure="no" failureproperty="junit.failure" printsummary="yes" maxmemory="10096m">
- 测试执行结果:
Tests run: 544, Failures: 1, Errors: 0, Time elapsed: 10,258.816 sec
- 异常栈:
[junit] Exception in thread "main" java.lang.OutOfMemoryError: Requested array size exceeds VM limit [junit] at java.lang.StringCoding$StringEncoder.encode(StringCoding.java:300) [junit] at java.lang.StringCoding.encode(StringCoding.java:344) [junit] at java.lang.StringCoding.encode(StringCoding.java:387) [junit] at java.lang.String.getBytes(String.java:958) [junit] at org.apache.tools.ant.taskdefs.optional.junit.PlainJUnitResultFormatter.endTestSuite(PlainJUnitResultFormatter.java:152) [junit] at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.fireEndTestSuite(JUnitTestRunner.java:619) [junit] at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.run(JUnitTestRunner.java:452) [junit] at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.launch(JUnitTestRunner.java:911) [junit] at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(JUnitTestRunner.java:768)
具体解决方案
1. 拆分测试套件,减少单次报告的内容量
一次性跑544个测试,生成的报告内容会非常庞大,尤其是如果每个测试都有详细输出或日志,很容易触发格式化器生成超大字符串。建议:
- 按业务模块、功能点把测试拆分成多个小套件(比如每个套件跑50-100个测试)
- 分别执行每个小套件,生成独立的报告文件
- 如果需要汇总报告,可以用Ant的
<concat>任务把多个报告合并,或者用第三方工具生成汇总结果
2. 替换默认的JUnit报告格式化器
默认的PlainJUnitResultFormatter会把整个测试套件的结果拼进一个字符串再写入文件,测试量一大就容易出问题。你可以:
- 自定义一个
JUnitResultFormatter实现类,在endTestSuite方法中分段写入报告内容,避免生成超大字符串 - 改用Ant提供的
XMLJUnitResultFormatter(XML格式报告是流式写入,不会一次性生成超大字符串),之后再用XSLT转换成你需要的文本格式
3. 升级Ant或JUnit版本
Ant 1.9.4是2014年的老版本,可能存在一些内存泄漏或格式化器的旧bug。尝试升级到:
- Ant 1.10.x系列(比如1.10.13,稳定的新版本)
- 匹配的JUnit版本(比如JUnit 4.13.2,确保和Ant的JUnit任务兼容)
新版本通常会修复这类边缘场景的问题。
4. 精简测试报告内容
如果不需要详细的测试输出,可以在JUnit任务中关闭不必要的配置:
- 把
printsummary="yes"改成printsummary="withOutAndErr"(只输出错误和异常日志) - 在
<test>或<batchtest>标签中添加forkmode="perTest",虽然会增加执行时间,但能减少单个进程的报告生成压力
内容的提问来源于stack exchange,提问作者navneet chandra
相关产品推荐
相关产品推荐

