Maven Surefire插件测试Java模块时遇STDOUT损坏与JVM终止问题
我遇到的问题和某Stack Overflow帖子的问题类似,但场景不同。我正在测试自己编写的Java模块,遵循Java模块化单元测试教程,使用JUnit 5,pom.xml中Surefire插件配置如下:
<plugin> <artifactId>maven-surefire-plugin</artifactId> <version>3.0.0-M5</version> <configuration> <argLine>--add-modules my.mod --add-opens my.mod/my.mod=org.junit.platform.commons --add-reads my.mod=org.junit.jupiter.api --patch-module my.mod=target/test-classes</argLine> </configuration> </plugin>
运行测试时先弹出警告:
[WARNING] Corrupted STDOUT by directly writing to native stream in forked JVM 1. See FAQ web page and the dump file
随后出现错误:
[ERROR] The forked VM terminated without properly saying goodbye. VM crash or System.exit called? [ERROR] Command was /bin/sh -c cd /xxx && /Library/Java/jdk-20.0.2.jdk/Contents/Home/bin/java --add-modules my.mod --add-opens my.mod/my.mod=org.junit.platform.commons --add-reads my.mod=org.junit.jupiter.api --patch-module my.mod=target/test-classes ...
我试过以下方案但没解决:
- 添加
<forkNode implementation="org.apache.maven.plugin.surefire.extensions.SurefireForkNodeFactory"/>后Maven挂起,偶尔出现引导层初始化错误 - 更换插件版本为3.0.0-M6、3.0.0-M4、3.1.2,问题依旧
可行的解决方向
补全模块权限配置
JUnit 5运行时可能需要更多反射权限,当前--add-opens只给了org.junit.platform.commons,建议补充引擎的权限:--add-opens my.mod/my.mod=org.junit.jupiter.engine同时确认
--patch-module指向的target/test-classes路径正确,且该目录下确实存在编译后的测试类。临时禁用fork模式排查
在Surefire插件配置里添加<forkCount>0</forkCount>,让测试在当前JVM运行,定位是否是fork模式导致的问题:<plugin> <artifactId>maven-surefire-plugin</artifactId> <version>3.1.2</version> <configuration> <forkCount>0</forkCount> <argLine>--add-modules my.mod --add-opens my.mod/my.mod=org.junit.platform.commons --add-reads my.mod=org.junit.jupiter.api --patch-module my.mod=target/test-classes</argLine> </configuration> </plugin>注:禁用fork可能影响测试隔离,但能快速定位问题根源。
排查代码中的原生流操作
警告提示“直接写入原生流”,说明测试或被测试代码里可能有绕过Java标准流的输出逻辑(比如JNI调用)。检查所有输出代码,或者在argLine中添加参数重定向流:-Dsurefire.useFile=false也可以在插件配置里直接设置:
<useFile>false</useFile>切换到JDK LTS版本
你当前使用的JDK 20是非LTS版本,可能和Surefire插件存在兼容性问题。建议切换到JDK 17(长期支持版)后重新运行测试。简化配置逐步排查
先把argLine简化到最基础的配置:--add-modules my.mod --patch-module my.mod=target/test-classes然后逐步添加
--add-opens和--add-reads参数,每次添加后运行测试,找到触发问题的具体配置项。
内容的提问来源于stack exchange,提问作者morpheus

