最近来到一个新项目,我试图编译我们的源代码。昨天一切都很好,但今天就不一样了。

每次我在一个模块上运行mvn clean install时,一旦到达测试,它就会崩溃成一个错误:

[INFO] --- maven-surefire-plugin:2.18.1:test (default-test) @ recorder ---
[INFO] Surefire report directory: /lhome/code/recorder/target/surefire-reports
[INFO] Using configured provider org.apache.maven.surefire.junitcore.JUnitCoreProvider
[INFO] parallel='none', perCoreThreadCount=true, threadCount=0, useUnlimitedThreads=false, threadCountSuites=0,     threadCountClasses=0, threadCountMethods=0, parallelOptimized=true

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Error: Could not find or load main class org.apache.maven.surefire.booter.ForkedBooter

Results :

Tests run: 0, Failures: 0, Errors: 0, Skipped: 0

后来:

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.18.1:test (default-test) on project recorder: Execution default-test of goal org.apache.maven.plugins:maven-surefire-plugin:2.18.1:test failed: The forked VM terminated without properly saying goodbye. VM crash or System.exit called?

我在Debian 9 (Stretch) 64位上运行,使用OpenJDK 1.8.0_181, Maven 3.5.4,在我的公司代理后面工作,我在~/.m2/settings.xml中配置了代理。

奇怪的是,如果我没记错的话,最新的Surefire版本是2.22.1。我试图指定插件版本,但它没有得到更新,否则任何POM(父、祖父或这个)中都没有插件版本规范。

我成功地迫使Maven将Surefire版本更改为最新版本,但现在情况更糟了:

[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 0, Failures: 0, Errors: 0, Skipped: 0

[...]

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.22.1:test (default-test) on project recorder:     There are test failures.
[ERROR]
[ERROR] Please refer to /lhome/code/recorder/target/surefire-reports for the individual test results.
[ERROR] Please refer to dump files (if any exist) [date].dump, [date]-jvmRun[N].dump and [date].dumpstream.
[ERROR] The forked VM terminated without properly saying goodbye. VM crash or System.exit called?
[ERROR] Command was /bin/sh -c cd /lhome/code/recorder/ && /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java     '-javaagent:/lhome1/johndoe/.m2/repository/org/jacoco/org.jacoco.agent/0.7.4.201502262128/org.jacoco.agent-0.7.4.201502262128-runt    ime.jar=destfile=/lhome/code/recorder/target/jacoco.exec,append=true,includes=esa/*,excludes=**/api/**/*.class' -jar     /lhome/code/recorder/target/surefire/surefirebooter7426165516226884923.jar /lhome/code/recorder/target/surefire     2018-10-26T16-16-12_829-jvmRun1 surefire1721866559613511529tmp surefire_023400764142672144tmp
[ERROR] Error occurred in starting fork, check output in log
[ERROR] Process Exit Code: 1
[ERROR] org.apache.maven.surefire.booter.SurefireBooterForkException: The forked VM terminated without properly saying goodbye.     VM crash or System.exit called?
[ERROR] Command was /bin/sh -c cd /lhome/code/recorder/ && /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java     '-javaagent:/lhome1/johndoe/.m2/repository/org/jacoco/org.jacoco.agent/0.7.4.201502262128/org.jacoco.agent-0.7.4.201502262128-runt    ime.jar=destfile=/lhome/code/recorder/target/jacoco.exec,append=true,includes=esa/*,excludes=**/api/**/*.class' -jar     /lhome/code/recorder/target/surefire/surefirebooter7426165516226884923.jar /lhome/code/recorder/target/surefire     2018-10-26T16-16-12_829-jvmRun1 surefire1721866559613511529tmp surefire_023400764142672144tmp
[ERROR] Error occurred in starting fork, check output in log
[ERROR] Process Exit Code: 1
[ERROR]     at org.apache.maven.plugin.surefire.booterclient.ForkStarter.fork(ForkStarter.java:669)
[ERROR]     at org.apache.maven.plugin.surefire.booterclient.ForkStarter.run(ForkStarter.java:282)
[ERROR]     at org.apache.maven.plugin.surefire.booterclient.ForkStarter.run(ForkStarter.java:245)
[ERROR]     at org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeProvider(AbstractSurefireMojo.java:1183)
[ERROR]     at     org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeAfterPreconditionsChecked(AbstractSurefireMojo.java:1011)
[ERROR]     at org.apache.maven.plugin.surefire.AbstractSurefireMojo.execute(AbstractSurefireMojo.java:857)
[ERROR]     at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:137)
[ERROR]     at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:208)
[ERROR]     at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:154)
[ERROR]     at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:146)
[ERROR]     at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:117)
[ERROR]     at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:81)
[ERROR]     at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:56)
[ERROR]     at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128)
[ERROR]     at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:305)
[ERROR]     at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:192)
[ERROR]     at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:105)
[ERROR]     at org.apache.maven.cli.MavenCli.execute(MavenCli.java:954)
[ERROR]     at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:288)
[ERROR]     at org.apache.maven.cli.MavenCli.main(MavenCli.java:192)
[ERROR]     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[ERROR]     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[ERROR]     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[ERROR]     at java.lang.reflect.Method.invoke(Method.java:498)
[ERROR]     at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
[ERROR]     at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
[ERROR]     at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)
[ERROR]     at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)

我发现了这个解决方法并修正了我的测试:配置maven-surefire-plugin不使用系统类加载器。


要修复它(在2018年),请将您的openjdk更新到最新版本,至少8u191-b12。如果这个问题在2020年再次出现,很可能是openjdk的默认行为被改变了,然后你将需要更新maven surefire插件。

这是openjdk-8包中的一个现已修复的错误(行为明显偏离上游而不需要;您刚刚升级到的上游补丁无法恢复到禁用安全检查)。但这也是surefire插件surefire -1588中的一个bug,应该在surefire 3.0.0-M1中修复了:它显然在Java未来只允许相对路径名的地方使用了绝对路径(Debian已经激活了未来的行为)。

8u181-b13-2版本说明:

应用8u191-b12安全更新中的补丁。

注意191-b12 != 181-b13。191-b12安全补丁几天前刚刚发布,显然维护者希望尽快将它们提供给您。完全更新到191-b12可能需要额外的测试(好吧,显然应该有这个上传)。

有几个变通办法:

You can install the previous package from snapshots.d.o instead. After downgrading, you can forbid the broken version (if you are using aptitude and not apt) using sudo aptitude forbid-version openjdk-8-jre-headless. For regular "apt" I didn't see a similar forbid mechanism, so you would likely need to use apt pinning to prevent this upgrade from being reinstalled (or you just keep on downgrading again, I hope this will be resolved soon). According to bug tracking, setting the property -Djdk.net.URLClassPath.disableClassPathURLCheck=true with any of the usual methods (e.g., JAVA_FLAGS) should also help. But I have not verified this myself. You can apparently even add the workaround to ~/.m2/settings.xml to get it enabled for all your Maven builds easily.

正如你所看到的,bug跟踪工作,问题被缩小了,一个固定的包是可用的,一个新版本的surefire插件将很快到来!


我在使用maven:3.5.4-jdk-8 Docker映像的GitLab CI构建中遇到了这个问题。

将其更改为maven:3.5.4-jdk-8-alpine修复了该问题。


对于那些寻找Docker Maven相关答案的人:3.5。在GitLab CI上的x-jdk-8,参见这个GitHub问题。

似乎是3.5.4-jdk-8镜像导致升级到一个小Java版本,这在某种程度上影响了Surefire的分叉机制。

回滚到3.5.3-jdk-8映像为我修复了这个问题,我的GitLab CI服务器使用Surefire 2.20.1构建Java 1.8代码。


如果你像我一样在你的管道中有问题(对我来说是在GitLab中,但不管怎样),如果你使用的是Maven JDK 8 Docker镜像。

你可以替换

image: maven:3.5.4-jdk-8

到最后一个工作构建

image: maven@sha256:b37da91062d450f3c11c619187f0207bbb497fc89d265a46bbc6dc5f17c02a2b

我有另一个变通办法。设置环境变量_JAVA_OPTIONS。我已经将此用于TeamCity构建代理,现在我们的构建运行良好。

_JAVA_OPTIONS=-Djdk.net.URLClassPath.disableClassPathURLCheck=true

将useSystemClassloader设置为false:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <configuration>
        <useSystemClassLoader>false</useSystemClassLoader>
    </configuration>
</plugin>

如果您没有从已经为您定义了版本(例如Spring Boot启动器)的父版本继承,那么您也需要定义该版本。


上面的建议设置属性“-Djdk.net.URLClassPath.disableClassPathURLCheck=true”没有为我工作,但设置以下工作OK:

-DforkCount=0

我在JIRA中发布了一个更有针对性的变种。添加到~/.m2/settings.xml:

<profile>
    <id>SUREFIRE-1588</id>
    <activation>
        <activeByDefault>true</activeByDefault>
    </activation>
    <properties>
        <argLine>-Djdk.net.URLClassPath.disableClassPathURLCheck=true</argLine>
    </properties>
</profile>

我遵循了这个链接https://maven.apache.org/surefire/maven-surefire-plugin/examples/class-loading.html,并在pom.xml中添加了下面的插件,它工作了,

<project>
  [...]
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.22.1</version>
        <configuration>
          <useSystemClassLoader>false</useSystemClassLoader>
        </configuration>
      </plugin>
    </plugins>
  </build>
  [...]
</project>

对于Ubuntu:安装最新版本,它已经修复了这个错误

sudo apt-get update ; sudo apt-get dist-upgrade -y

安装没有该错误的最后一个工作版本(没有安全补丁)。

sudo apt-get install openjdk-8-jdk-headless=8u181-b13-1 openjdk-8-jdk=8u181-b13-1  openjdk-8-jre=8u181-b13-1  openjdk-8-jre-headless=8u181-b13-1 openjdk-8-source=8u181-b13-1

如果你错过了那个版本,请使用之前的版本:

sudo apt-get install openjdk-8-jdk-headless=8u162-b12-1 openjdk-8-jdk=8u162-b12-1  openjdk-8-jre=8u162-b12-1  openjdk-8-jre-headless=8u162-b12-1 openjdk-8-source=8u162-b12-1

然后使用固定或注意你不会安装坏的版本。

使用-Djdk.net.URLClassPath.disableClassPathURLCheck=true没有为我工作,无论我把配置放在哪里。在我的集成测试中,它总是在没有旧Java版本的情况下退出。

正如Erich所提到的,这是Debian包中的一个bug,过于严格的911925和Surefire-plugin没有按照新规则SUREFIRE-1588行事。


我卸载了软件库中的JDK:

$ sudo apt purge openjdk-8-jdk

$ sudo apt autoremove

然后我删除了JAVA_HOME环境变量。我的设置在。bashrc中。

然后我通过SDKMAN重新安装:

$ sdk install java 8.0.181-zulu

从他们的网站:

SDKMAN !是一个工具,用于在大多数基于Unix的系统上管理多个软件开发工具包的并行版本。它提供了一个方便的命令行接口(CLI)和API,用于安装、切换、删除和列出候选。

要查看要安装的其他版本的JDK,请使用:

$ sdk list java

我最近在詹金斯上设置了专家工作,陷入了同样的问题。我采纳了修改JAVA env变量的建议,并确认问题已经解决。这就是我的测试方法。

成为“jenkins”用户,并将文件夹更改为为作业设置的工作区项目名称。

 $ _JAVA_OPTIONS=-Djdk.net.URLClassPath.disableClassPathURLCheck=true mvn clean install -U

 $ lsb_release -rd
 Description:   Ubuntu 16.04.5 LTS
 Release:   16.04

 $ mvn -v
 Apache Maven 3.3.9
 Maven home: /usr/share/maven
 Java version: 1.8.0_181, vendor: Oracle Corporation
 Java home: /usr/lib/jvm/java-8-openjdk-amd64/jre
 Default locale: en_US, platform encoding: UTF-8
 OS name: "linux", version: "4.4.0-131-generic", arch: "amd64", family: "unix"

我在使用gitlab ci时也遇到了同样的问题,将maven映像从maven:3-jdk-8更改为maven:3.6.0-jdk-8-alpine似乎解决了这个问题。顺便说一句,我也用maven:3.6.0-jdk-8进行了测试,但它也不能工作。


当使用带有3.6.0-jdk-8 image的GitLab CI/CD时,只有下面的属性有帮助(不修改pom.xml)。

-Dsurefire.useSystemClassLoader=false

我向junit-jupiter-engine添加了依赖项,它工作了。

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.22.1</version>
    <dependencies>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>5.4.0</version>
        </dependency>
    </dependencies>
</plugin>

把这个添加到maven-surefire-plugin中,我解决了这个问题:

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

对于surefire - v2.22.2和maven:3.6-jdk-8-alpine来说,这仍然是一个问题。要解决这个问题,将以下代码添加到pom.xml(作为maven插件)

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

基本上是JDK版本和maven-surefire插件版本之间的不兼容,在我的情况下,JDK 11.0.5不能与surefire 3.0.0-M4兼容,我必须切换到3.0.0-M3,它可以工作。将forkCount设置为0并不能解决这个问题,因为它破坏了Jacoco报告。


对我来说,在Visual Studio Code中

我没有对pom.xml文件做任何更改,也没有更新任何依赖项版本 将这一行添加到设置中。Visual Studio Code的json解决了这个问题。

"maven.executable.options": "-DforkCount=0",