调试surefire的策略“分叉的虚拟机终止而没有说再见。虚拟机崩溃或System.exit被调用?”

时间:2013-12-17 19:12:23

标签: java maven maven-surefire-plugin

我正在开发一个相当复杂的java项目,它包含许多依赖项和许多单元测试。

我在mac(mavericks)上使用java 1.6.0_65,使用maven 3.0.5和maven-surefire-plugin:2.16在几个forks中运行。 我的问题是,使用多个forks运行此设置会导致fork退出:

  

“分叉的虚拟机终止,没有说再见。虚拟机崩溃或   System.exit调用了吗?“

只使用一个fork运行它不会产生问题(并且一切都通过了)

有一些关于此问题的信息,包括this StackOverflow questionthis surefire bug(现在似乎已解决)

我知道对这种情况的“回答”是找到我的代码中调用System.exit()的东西 - 我找不到任何东西。

或者是什么原因导致我的JVM崩溃 - 没有hs_pid崩溃报告。

我的问题是我可以用什么样的策略找到找到这个原因的方法? 为了澄清,我对上面提到的答案不感兴趣,但是找到它的起源。 (或者甚至更好地回答可能造成这种情况的不同答案)


我的Surefire配置是:(但我确实尝试过其他组合)

<parallel>classes</parallel>
<threadCount>1</threadCount>
<forkCount>1C</forkCount>
<reuseForks>false</reuseForks>
<useSystemClassLoader>false</useSystemClassLoader>
<useManifestOnlyJar>true</useManifestOnlyJar>
<useFile>true</useFile>
<redirectTestOutputToFile>true</redirectTestOutputToFile>
<runOrder>alphabetical</runOrder>

更新#1 在使用--debug(-X)

运行maven目标后添加相关输出
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.16:test (default-test) on project event-logger: ExecutionException; nested exception is java.util.concurrent.ExecutionException: java.lang.RuntimeException: The forked VM terminated without saying properly goodbye. VM crash or System.exit called ?
[ERROR] Command was/bin/sh -c cd /Users/nitzan/work/nitzan_5_parallel_tests/event-logger && /Library/Java/JavaVirtualMachines/1.6.0_65-b14-462.jdk/Contents/Home/bin/java org.apache.maven.surefire.booter.ForkedBooter /Users/nitzan/work/nitzan_5_parallel_tests/event-logger/target/surefire/surefire5107531798951225850tmp /Users/nitzan/work/nitzan_5_parallel_tests/event-logger/target/surefire/surefire_12561116468761732560tmp
[ERROR] -> [Help 1]
org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.16:test (default-test) on project event-logger: ExecutionException; nested exception is java.util.concurrent.ExecutionException: java.lang.RuntimeException: The forked VM terminated without saying properly goodbye. VM crash or System.exit called ?
Command was/bin/sh -c cd /Users/nitzan/work/nitzan_5_parallel_tests/event-logger && /Library/Java/JavaVirtualMachines/1.6.0_65-b14-462.jdk/Contents/Home/bin/java org.apache.maven.surefire.booter.ForkedBooter /Users/nitzan/work/nitzan_5_parallel_tests/event-logger/target/surefire/surefire5107531798951225850tmp /Users/nitzan/work/nitzan_5_parallel_tests/event-logger/target/surefire/surefire_12561116468761732560tmp
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:213)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:84)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:59)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.singleThreadedBuild(LifecycleStarter.java:183)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:161)
    at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:320)
    at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:156)
    at org.apache.maven.cli.MavenCli.execute(MavenCli.java:537)
    at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:196)
    at org.apache.maven.cli.MavenCli.main(MavenCli.java:141)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:290)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:230)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:409)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:352)
    at org.codehaus.classworlds.Launcher.main(Launcher.java:47)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Caused by: org.apache.maven.plugin.MojoFailureException: ExecutionException; nested exception is java.util.concurrent.ExecutionException: java.lang.RuntimeException: The forked VM terminated without saying properly goodbye. VM crash or System.exit called ?
Command was/bin/sh -c cd /Users/nitzan/work/nitzan_5_parallel_tests/event-logger && /Library/Java/JavaVirtualMachines/1.6.0_65-b14-462.jdk/Contents/Home/bin/java org.apache.maven.surefire.booter.ForkedBooter /Users/nitzan/work/nitzan_5_parallel_tests/event-logger/target/surefire/surefire5107531798951225850tmp /Users/nitzan/work/nitzan_5_parallel_tests/event-logger/target/surefire/surefire_12561116468761732560tmp
    at org.apache.maven.plugin.surefire.SurefirePlugin.assertNoException(SurefirePlugin.java:198)
    at org.apache.maven.plugin.surefire.SurefirePlugin.handleSummary(SurefirePlugin.java:188)
    at org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeAfterPreconditionsChecked(AbstractSurefireMojo.java:852)
    at org.apache.maven.plugin.surefire.AbstractSurefireMojo.execute(AbstractSurefireMojo.java:720)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:101)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:209)
    ... 25 more
Caused by: org.apache.maven.surefire.booter.SurefireBooterForkException: ExecutionException; nested exception is java.util.concurrent.ExecutionException: java.lang.RuntimeException: The forked VM terminated without saying properly goodbye. VM crash or System.exit called ?
Command was/bin/sh -c cd /Users/nitzan/work/nitzan_5_parallel_tests/event-logger && /Library/Java/JavaVirtualMachines/1.6.0_65-b14-462.jdk/Contents/Home/bin/java org.apache.maven.surefire.booter.ForkedBooter /Users/nitzan/work/nitzan_5_parallel_tests/event-logger/target/surefire/surefire5107531798951225850tmp /Users/nitzan/work/nitzan_5_parallel_tests/event-logger/target/surefire/surefire_12561116468761732560tmp
    at org.apache.maven.plugin.surefire.booterclient.ForkStarter.runSuitesForkPerTestSet(ForkStarter.java:316)
    at org.apache.maven.plugin.surefire.booterclient.ForkStarter.run(ForkStarter.java:169)
    at org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeProvider(AbstractSurefireMojo.java:958)
    at org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeAfterPreconditionsChecked(AbstractSurefireMojo.java:822)
    ... 28 more
Caused by: java.util.concurrent.ExecutionException: java.lang.RuntimeException: The forked VM terminated without saying properly goodbye. VM crash or System.exit called ?
Command was/bin/sh -c cd /Users/nitzan/work/nitzan_5_parallel_tests/event-logger && /Library/Java/JavaVirtualMachines/1.6.0_65-b14-462.jdk/Contents/Home/bin/java org.apache.maven.surefire.booter.ForkedBooter /Users/nitzan/work/nitzan_5_parallel_tests/event-logger/target/surefire/surefire5107531798951225850tmp /Users/nitzan/work/nitzan_5_parallel_tests/event-logger/target/surefire/surefire_12561116468761732560tmp
    at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:222)
    at java.util.concurrent.FutureTask.get(FutureTask.java:83)
    at org.apache.maven.plugin.surefire.booterclient.ForkStarter.runSuitesForkPerTestSet(ForkStarter.java:300)
    ... 31 more
Caused by: java.lang.RuntimeException: The forked VM terminated without saying properly goodbye. VM crash or System.exit called ?
Command was/bin/sh -c cd /Users/nitzan/work/nitzan_5_parallel_tests/event-logger && /Library/Java/JavaVirtualMachines/1.6.0_65-b14-462.jdk/Contents/Home/bin/java org.apache.maven.surefire.booter.ForkedBooter /Users/nitzan/work/nitzan_5_parallel_tests/event-logger/target/surefire/surefire5107531798951225850tmp /Users/nitzan/work/nitzan_5_parallel_tests/event-logger/target/surefire/surefire_12561116468761732560tmp
    at org.apache.maven.plugin.surefire.booterclient.ForkStarter.fork(ForkStarter.java:485)
    at org.apache.maven.plugin.surefire.booterclient.ForkStarter.fork(ForkStarter.java:352)
    at org.apache.maven.plugin.surefire.booterclient.ForkStarter.access$300(ForkStarter.java:85)
    at org.apache.maven.plugin.surefire.booterclient.ForkStarter$2.call(ForkStarter.java:288)
    at org.apache.maven.plugin.surefire.booterclient.ForkStarter$2.call(ForkStarter.java:283)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
    at java.util.concurrent.FutureTask.run(FutureTask.java:138)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
    at java.lang.Thread.run(Thread.java:695)
[ERROR] 
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException

11 个答案:

答案 0 :(得分:9)

步骤:

(1)使用-e-X选项运行mvn以获取更多调试信息。

(2)寻找&#34;错误&#34;在输出中。在我的例子中,当我运行mvn命令时,输出的一部分包括:

[ERROR] Command wascmd.exe /X /C "C:\dev\dev-tools\.....

(3)直接在命令shell中执行有问题的命令。

就我而言,执行

cmd.exe /X /C "C:\dev\dev-tools\....
命令行中的

导致OutOfMemoryError。

答案 1 :(得分:3)

根据Maven Surefire文档,如果始终失败,您可以在debug mode中执行分叉的VM。然后,您可以调试代码,直到它退出。

答案 2 :(得分:3)

FWIW,当maven构建期间JVM内存不足时,我遇到了这个错误。在Linux上,这是由OOM杀手检测到的,它最终生成了类似的内核消息 Aug 28 20:53:27 ip-xxx-xxx-xxx-xxx kernel: [248686.775455] java invoked oom-killer: gfp_mask=0x201da, order=0, oom_score_adj=0

我想在Mac上你只想用ActivityMonitor来监控你的内存使用情况。

答案 3 :(得分:2)

在这里写下我用来帮助其他人解决这个问题的策略。

可以在调用System.exit()时利用SecurityManager引发异常。然后,您可以检查堆栈跟踪以查看究竟是谁调用exit()。 如果对exit的调用是由隐藏在您所依赖的某个jar中的代码而不是您自己的代码中调用,则此功能特别有用。

private static void forbidSystemExitCall() {
    final SecurityManager securityManager = new SecurityManager() {
        public void checkPermission( Permission permission ) {
            if( permission.getName().startsWith("exitVM") ) {
                throw new RuntimeException("Something called exit ") ;
            }
        }
    } ;
    System.setSecurityManager( securityManager ) ;
}  

答案 4 :(得分:2)

如果有人包含自定义argLine参数,则必须重新考虑,因为它可能是内存分配问题的根源。

例如(我以前):

<argLine>XX:MaxPermSize=4096m ${argLine}</argLine>

现在我使用硬指定值:

<argLine>-Xmx1024m -XX:MaxPermSize=256m</argLine>

无论出于何种原因,与Socofire集成的应用程序(如Jacoco)不要求足够的内存与构建时发生的测试共存。

(更多信息也可在此s.o.问题(1)中找到)

(1) - maven jacoco: not generating code coverage report

答案 5 :(得分:1)

您可能想要检查的是你的pom中build / pluging / plugin配置中的surefire或failsafe的argline设置。我有一些不正确的东西导致分叉的虚拟机失败(具有讽刺意味的是,我把maven.failsafe.debug放在那里以帮助调试早先的分叉崩溃)。

答案 6 :(得分:1)

更改插件的配置应该可以解决问题:

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

如本插件post和插件主插件documentation中所述。

答案 7 :(得分:0)

可以提供帮助的JVM选项:

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=c:/dumps/

注意:您可以使用正斜杠 注意2:确保该文件夹存在且该进程具有写入权限。在最近的Windows系统上,C:\被写保护 注3:确保有足够的可用空间来编写转储。 Java 9文档提到磁盘已满时将使用系统的临时文件夹。

如果没有转储文件,那么JVM就没有内存不足。

下一个选项是-XX:ErrorFile=,它允许JVM记录致命错误。

如果JVM崩溃,

-XX:+ShowMessageBoxOnError会显示错误对话框。

注意:您可以使用jinfo命令更改正在运行的JVM的标志。

通过argLine选项将这些选项传递给Maven Surefire:

<build>
    <plugins>
        <plugin>
            <artifactId>maven-surefire-plugin</artifactId>
            <configuration>
                <!-- -XX:HeapDumpPath=C:\ -XX:+ShowMessageBoxOnError  -->
                <argLine>@{argLine} -XX:+HeapDumpOnOutOfMemoryError -Xmx1g -XX:HeapDumpPath=H:/dumps/ -XX:ErrorFile=H:/dumps/ -XX:+ShowMessageBoxOnError</argLine>
            </configuration>
        </plugin>
    </plugins>
</build>

开头的奇怪@{argLine}允许像Jacoco这样的其他插件注入他们的选项。为此,您需要添加一个空属性:

<properties>
    <argLine></argLine> <!-- Fallback when Jacoco isn't active. -->
</properties>

您可以在发生错误时验证它是否有效:Maven将转储用于启动分叉JVM的整个命令行。

答案 8 :(得分:0)

我只是删除所有Maven存储库并运行Maven全新安装。然后问题就解决了。

答案 9 :(得分:0)

在我的情况下,maven-surefire-plugin的forkedProcessExitTimeoutInSeconds配置很有帮助。自maven-surefire-plugin:2.20.1 30秒以来为默认值。我的项目进行了非常耗时的测试,因此分叉的JVM崩溃了。 使用以下属性在pom中配置插件即可解决此问题。

<plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <configuration>
                <forkedProcessExitTimeoutInSeconds>120</forkedProcessExitTimeoutInSeconds>
        </configuration>
</plugin>

答案 10 :(得分:0)

如果您使用的是Visual Studio代码

我没有对pom.xml文件进行任何更改,也没有更新任何依赖项版本
将此行添加到Visual Studio Code的settings.json中可以解决此问题。

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