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.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.out
或System.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 forkMode
和 forNode
是 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