Surefire Maven 插件: “通过直接写入分叉 JVM 中的本机流而损坏的 STDOUT”

我的 JUnit 测试在通过 Maven 和 Surefire 插件(下面的版本信息)运行时失败。我看到了错误消息:

Corrupted STDOUT by directly writing to native stream in forked JVM 4. See FAQ web page and the dump file C:\(...)\target\surefire-reports\2019-03-20T18-57-17_082-jvmRun4.dumpstream

FAQ 页面指出了一些可能的原因,但我不知道如何利用这些信息来开始解决这个问题:

通过直接写入分叉 JVM 中的本机流来损坏 STDOUT

如果您的测试使用的本机库打印到 STDOUT,这个警告消息会出现,因为该库损坏了插件使用的通道,以便将具有测试状态的事件传输回 Maven 进程。如果您通过 System.setOut 覆盖 Java 流,情况会更糟,因为流也应该被破坏,但 Maven 将永远不会看到测试完成,构建可能会挂起。

如果使用 FileDescriptor.out 或 JVM 打印 GC 摘要,则会出现此警告消息。

在这种情况下,警告打印为“通过直接写入分叉 JVM 中的本机流损坏的 STDOUT”,并且可以在 Reports 目录中找到转储文件。

如果启用了调试级别,则控制台中将显示已损坏流的消息。

它指的是一些直接打印到 STDOUT 的本地库,但是如何才能找出是哪一个,即使我这样做了,如果我的项目需要这个库,我该如何处理这个问题?

它提到了“调试级别”,但不清楚这是指 Maven 的调试级别还是 Surefire 插件的调试级别。我启用了 Maven 的调试,但是我没有看到 FAQ 中提到的控制台输出。而且 Surefire 的调试选项似乎是关于暂停测试并等待调试器连接到进程,而不是简单地在控制台上显示更多信息。

转储文件似乎也没有多大帮助:

# Created on 2019-03-20T18:42:58.323
Corrupted STDOUT by directly writing to native stream in forked JVM 2. Stream 'FATAL ERROR in native method: processing of -javaagent failed'.
java.lang.IllegalArgumentException: Stream stdin corrupted. Expected comma after third character in command 'FATAL ERROR in native method: processing of -javaagent failed'.
at org.apache.maven.plugin.surefire.booterclient.output.ForkClient$OperationalData.<init>(ForkClient.java:511)
at org.apache.maven.plugin.surefire.booterclient.output.ForkClient.processLine(ForkClient.java:209)
at org.apache.maven.plugin.surefire.booterclient.output.ForkClient.consumeLine(ForkClient.java:176)
at org.apache.maven.plugin.surefire.booterclient.output.ThreadedStreamConsumer$Pumper.run(ThreadedStreamConsumer.java:88)
at java.base/java.lang.Thread.run(Thread.java:834)

那么,我该如何解决这个问题呢?

更新 : 请求的配置信息如下。

我在 Windows 10、 Maven 3.5.3和 Surefire 2.21.0(下面是完整配置)上使用 OpenJDK 11(Zulu 发行版)。

我在 Eclipse 中使用 pom.xml文件上的“ Run As...”上下文菜单选项运行 Maven,但是在控制台上运行时获得相同的结果。

在这个问题的第一条注释之前,我从未听说过 JaCoco,但是我看到了几条提到它的错误消息:

[ERROR] ExecutionException The forked VM terminated without properly saying goodbye. VM crash or System.exit called?
[ERROR] Command was cmd.exe /X /C ""C:\Program Files\Zulu\zulu-11\bin\java" -javaagent:C:\\Users\\E26638\\.m2\\repository\\org\\jacoco\\org.jacoco.agent\\0.8.0\\org.jacoco.agent-0.8.0-runtime.jar=destfile=C:\\Users\\E26638\\git\\aic-expresso\\target\\jacoco.exec -Xms256m -Xmx1028m -jar C:\Users\E26638\AppData\Local\Temp\surefire10089630030045878403\surefirebooter8801585361488929382.jar C:\Users\E26638\AppData\Local\Temp\surefire10089630030045878403 2019-03-21T21-26-04_829-jvmRun12 surefire10858509118810158083tmp surefire_115439010304069944813tmp"
[ERROR] Error occurred in starting fork, check output in log
[ERROR] Process Exit Code: 1

这是 Surefire Maven 的插件配置:

    <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.21.0</version>
<configuration>
<skipTests>${skipUnitTests}</skipTests>
<testFailureIgnore>false</testFailureIgnore>
<forkCount>1.5C</forkCount>
<reuseForks>true</reuseForks>
<parallel>methods</parallel>
<threadCount>4</threadCount>
<perCoreThreadCount>true</perCoreThreadCount>
<reportFormat>plain</reportFormat>
<trimStackTrace>false</trimStackTrace>
<redirectTestOutputToFile>true</redirectTestOutputToFile>
</configuration>
</plugin>
62049 次浏览

在将项目从 JAVA 8迁移到 JAVA 11时遇到同样的问题,将 jacoco-plugin 从0.8.1升级到0.8.4就可以解决这个问题。

分析 maven 依赖关系,查看 Jacoco 的位置,然后修复版本应该可以解决这个问题。

对我来说,它是将故障保护插件从2.22.0升级到2.22.2

对我来说,解决这个问题的办法是将 maven surefire 插件升级到2.22.2

最新的 Surefire 插件版本是完全错误和破碎的。 对我来说(一直测试到 Java12)唯一的解决方案就是坚持使用 2.20

也不要使用2.20.1,它在 NPE 中失败了,尽管它可能是特定于特定测试的,但是我没有时间去研究它。

在使用自定义 Runner 运行我的 Junit 测试时遇到了这个问题。如果我在自定义运行程序或测试类中对 System.outSystem.err做了任何输出,就会显示这个确切的警告。在我的案例中,问题并不是由一些旧的 Jacoco 版本引起的。将 surefire 插件更新到版本2.22.2或更新的3.0.0-M4并没有解决这个问题。

根据 Jira 问题 SUREFIRE-1614 ,这个问题将在 maven-surefire-plugin 的3.0.0-M5版本(2020年5月21日还没有发布)中得到解决。

更新 Maven Surefire 插件版本3.0.0-M5已经发布:

    <plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
<configuration>
<!-- Activate the use of TCP to transmit events to the plugin -->
<forkNode implementation="org.apache.maven.plugin.surefire.extensions.SurefireForkNodeFactory"/>
</configuration>
</plugin>

原始答案

如果您不能等待3.0.0-M5插件的发布,您可以使用该插件的“ SNAPSHOT”版本。它确实帮我解决了问题。您必须在插件中启用一些特定的设置,以便插件使用 TCP 而不是标准的输出/错误来获取测试中引发的事件。配置变化如下:

在我的 pom.xml中:

<?xml version="1.0" encoding="UTF-8"?>


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>


...
<!-- Add the repository to download the "SNAPSHOT" of maven-surefire-plugin -->
<pluginRepositories>
<pluginRepository>
<id>apache.snapshots</id>
<url>https://repository.apache.org/snapshots/</url>
</pluginRepository>
</pluginRepositories>


<build>
<pluginManagement>
<plugins>
...
<artifactId>maven-surefire-plugin</artifactId>
<!-- Use the SNAPSHOT version -->
<version>3.0.0-SNAPSHOT</version>
<configuration>
<!-- Activate the use of TCP to transmit events to the plugin -->
<forkNode implementation="org.apache.maven.plugin.surefire.extensions.SurefireForkNodeFactory"/>
</configuration>
</plugin>


我在 Intelij Ideas 中运行 Maven build 时遇到了这个错误。我在不同的窗口中打开了几个项目,并且在另一个项目中出现了其他奇怪的错误。

通过关闭所有 Intellij Ideas 窗口并重新打开项目,我解决了这个问题。

对我来说,这是升级 org.testng到最新版本(7.3.0)

所有列出的答案对我们的案子都没有帮助。这个问题始于我们从 Java8升级到 Java11之后。

注意: 在我们的案例中,更新 Surefire 插件是不可能的,因为它破坏了我们项目中测试所依赖的一些机制——检查这个问题花费了太长时间,所以我们开始在 Jacoco 找出这种行为的根本原因。

在一些调试和 JVM 转储之后,我们发现了原因: 在我们的例子中,类路径上有 JavaFX 依赖项,这些依赖项是由一个解析器 util 自动加载的。在启用了 jacoco 的情况下加载这些类会导致 JVM 崩溃(在我们的例子中,没有使用 jacoco 封装在概要文件的“覆盖率”中,这种情况下运行得很好)。排除从 JavaFX 库中加载类(在我们的例子中不需要)可以解决这个问题。现在测试在没有 JVM 崩溃的情况下运行得很好。

在我们的例子中,导致 JVM 崩溃(或者至少是之前加载的最后一个)的确切类是: com.sun.javafx.logging.jfr.JFRPulsePhaseEvent Jar: javafx-base-12-win. Jar

提示: 在许多 IDE 中,您可以使用特定的配置文件调试 Maven 构建,并检查到底发生了什么。

使用 Jacoco0.8.6和 Surefire 插件2.22.2

如果您无法升级到最新的 JaCoCo 版本,我也可以通过将 forkCount设置为 0来修复我的项目:

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.0</version>
<configuration>
<forkCount>0</forkCount>
</configuration>
</plugin>

这个问题也随机发生在我身上

我在吸毒

IntelliJ IDEA 2020 (Community Edition)
Surefire plugin (3.0.0-M5)
Maven 3.3.9
AdoptOpenJDK 11

这种情况通常发生在几分钟后的 Windows10上 美丽的蓝色死亡屏幕。

重新启动后,一切又恢复正常

在我的案例中,我将我的开发移动到一个新的 PC 上,并且在我的 Maven-repo 中还没有我们公司的所有库依赖。所以当 Maven 运行时,缺少了这样一个库,我不得不用 mvn install:install-file ...安装它。

因此,重要的是要阅读最新的注定失败的日志,因为它暗示了这些事情。

不知道,为什么 surefire-plugin 不只是在 STDOUT 上打印冲突的行到控制台,所以在不到一秒钟的时间内就会显而易见。

我们正在使用 log4j 后端,也可以修复它使用 follow设置为 true

<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="${messagePattern}" />
<follow>true</follow>
</Console>
</Appenders>

(我们有相同的错误消息,但没有涉及 Jacoco。但我可以确认,将 maven-surefire-plugin中的 forkNode设置为 TCP 也是有效的。)