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

Posted

技术标签:

【中文标题】Surefire Maven 插件:“通过直接写入分叉 JVM 中的本机流来破坏 STDOUT”【英文标题】:Surefire Maven plugin: "Corrupted STDOUT by directly writing to native stream in forked JVM" 【发布时间】:2019-08-11 20:40:45 【问题描述】:

我的 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 的调试,但我没有看到常见问题解答中提到的控制台输出。而且 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 发行版)。

我正在使用 pom.xml 文件上的“运行方式...”上下文菜单选项从 Eclipse 运行 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>

【问题讨论】:

首先,了解更多信息会有所帮助。您使用哪个 Maven 版本、JDK 版本、Surefire 版本?你在使用 JaCoco 吗?你怎么称呼Maven?等等? 谢谢你,@khmarbaise。我已根据您要求的信息更新了问题。 先将插件升级到最新版本maven.apache.org/plugins 对我来说更新 jacoco-maven-plugin 解决了这个问题 @ticktock 的评论是我对这个问题的看法。也适用于我。 Jacoco 版本 - 0.8.4,jdk 11.0.3 【参考方案1】:

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

分析 maven 依赖关系,查看 jacoco 是从哪里拉出来的,然后修复版本应该可以解决问题。

【讨论】:

我遇到了完全相同的问题。但是,我使用的是旧版本 0.7.7.201606060606。看起来这个问题已在上一个版本 0.8.4 中得到解决。 也为我工作,谢谢!我将一个项目从 Java 12 迁移到 Java 13。 我没有在迁移到 JUnit 5 后失败的项目中使用 Jacoco,但与其他项目(使用 Jacoco 0.8.4)一样,停留在 Surefire 插件 2.19 或 2.20他们,除非与 Java 17 或 21 的主要不兼容性迫使我这样做,否则我不会超过 ;-) 拯救了我的一天。非常感谢 3.0.0-M5版本应该没有问题,但是你应该用配置插件【参考方案2】:

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

【讨论】:

帮助我。这是导致STDOUT 问题的错误的链接:SUREFIRE-1614 这也是我的解决方案。 Java 11,macOS 10.14.5。【参考方案3】:

为我解决的问题是将 maven surefire 插件升级到 2.22.2

【讨论】:

【参考方案4】:

较新的 Surefire 插件版本完全有缺陷和损坏。 对我来说(一直测试到 Java 12)唯一的解决方案是坚持使用 2.20

也不要使用 NPE 失败的 2.20.1,虽然它可能是特定于特定测试的,但我没有时间调查。

【讨论】:

也许只是在 jira 上创建一个问题。如果您有公共代码,那也会有所帮助。 问题是,Surefire 项目页面已经提到了它,但它完全模糊,崩溃时的转储也是如此。 Werner,如果您不创建问题,它将永远无法修复。也许您的情况不同,如果您不提供额外信息,surefire 团队怎么会知道?【参考方案5】:

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

According to the Jira issue SUREFIRE-1614,该问题将在 maven-surefire-plugin 的 3.0.0-M5 版本中修复(截至 2020 年 5 月 21 日尚未发布)。

更新 Maven Surefire 插件版本 3.0.0-M5 现已发布。在您的 pom.xml 中,您可以执行以下操作:

    <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>

【讨论】:

3.0.0-M5 版本即将发布。我们必须完成 JPMS 问题。修复的要求越来越高。 请注意,真正的修复不在 SUREFIRE-1614 中,而是在 SUREFIRE-1788 中。另请注意,有时在使用快照或 RC1 版本(有时会更新,而不是固定版本)时,构建会挂起,所以肯定有另一个问题希望在 M5 之前得到修复。 有一个错字 - s/b forkMode, not forkNode in 感谢@Sasha 的精心校对。但是,我认为您在这种情况下是错误的。 forkModeforNode 是 surefire 和 failsafe 插件的两个不同设置。 forkMode 允许您 choose if and how tests are executed in parallel 而我的回答中讨论的 forkNode 与 Surefire 插件如何与运行测试的分叉 JVM 通信有关。 说到错别字,我刚刚注意到我的评论中有一个错别字。它应该读作“forkNode”,而不是“forNode”。不幸的是,修复它为时已晚 XD。【参考方案6】:

我在 Intelij Idea 中运行 Maven 构建时遇到此错误。我在不同的窗口中打开了几个项目,并且在不同的项目中出现了其他奇怪的错误。

通过关闭所有 Intellij Idea 窗口并重新打开项目为我解决了问题。没有更改任何依赖项版本。

【讨论】:

当我尝试增加 Intellij IDEA 使用的内存并且不得不重新启动以使其生效时,这确实为我解决了这个问题。【参考方案7】:

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

【讨论】:

【参考方案8】:

在我们的案例中,列出的答案都没有帮助。这个问题是在我们从 Java 8 升级到 Java 11 之后开始的。

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

经过一些调试和 JVM 转储,我们找到了原因:在我们的例子中,类路径上有 JavaFX 依赖项,这些依赖项是由解析器实用程序自动加载的。在启用 jacoco 的情况下加载这些类会导致 JVM 崩溃(没有 jacoco——在我们的例子中封装在配置文件“覆盖”中——运行良好)。排除从 JavaFX 库加载类(在我们的例子中不需要)解决了这个问题。现在测试运行良好,没有 JVM 崩溃。

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

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

使用 Jacoco 0.8.6 和 Surefire 插件 2.22.2

【讨论】:

真是一场噩梦!【参考方案9】:

如果您无法升级到最新的 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>

【讨论】:

【参考方案10】:

这个问题我也遇到过

我正在使用

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

当它发生时,Windows 10 通常会在几分钟后显示 漂亮的蓝屏死机。

然后重启后一切恢复正常

【讨论】:

哇,这太不可思议了。我是 Surefire 的开发人员。蓝屏可能与 Windows 或 JDK 有关。也许我们会在看到位于 target/surefire-reports 中的转储文件后了解更多。你能给我看看这些文件吗?【参考方案11】:

在我的情况下,我将我的开发转移到了一台新 PC,并且我的 Maven 存储库中还没有我们所有的公司库依赖项。因此,当 Maven 运行时,缺少这样的库,我必须使用 mvn install:install-file ... 安装它。

因此,阅读最新的肯定日志很重要,因为它暗示了这些内容。

不知道,为什么 surefire-plugin 不只是将 STDOUT 上的冲突行打印到控制台,所以不到一秒钟就会很明显。

【讨论】:

以上是关于Surefire Maven 插件:“通过直接写入分叉 JVM 中的本机流来破坏 STDOUT”的主要内容,如果未能解决你的问题,请参考以下文章

如何将 maven 插件转换为 gradle 插件(maven-surefire-puglin)?

在测试执行 Maven Surefire 插件时排除日志跟踪

jacoco 插件不适用于 sunfire 插件.. org.apache.maven.surefire.booter.SurefireBooterForkException

maven-surefire-plugin插件

如何使 maven cobertura 和 surefire 插件一起工作?

maven-surefire 插件没有运行少数 Junit5 测试配置文件