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

我正在开发一个相当复杂的java项目,它有许多依赖项和许多unit testing。

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

“分叉的虚拟机在没有说再见的情况下终止。虚拟机崩溃或System.exit被调用?”

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

有一些关于这个问题的信息,包括这个StackOverflow问题和这个万无一失的bug (现在似乎已经解决了)

我知道这种情况的“答案”是在我的代码中找到什么叫System.exit() – 我找不到任何东西。

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

我的问题是我可以用什么样的策略找到找到这个原因的? 为了澄清,我对上面提到的答案不感兴趣,但是找到它的起源。 (或者甚至更好地说明可能导致此问题的不同答案)


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

classes 1 1C false false true true true alphabetical 

在使用–debug(-X)运行maven目标后添加#1添加相关的输出

 [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 

脚步:

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

(2)在输出中查找“错误”。 在我的例子中,当我运行mvn命令时,部分输出包括:

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

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

在我的情况下,执行

 cmd.exe /X /C "C:\dev\dev-tools\.... 

从命令行导致OutOfMemoryError。

在Maven Surefire文档之后,如果始终失败,您可以在调试模式下执行分叉VM。 然后,您可以调试代码,直到退出。

在这里写下我用来帮助那些坚持这个问题的人的策略。

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

 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 ) ; } 

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来监控你的内存使用情况。

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

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

例如(我以前):

 XX:MaxPermSize=4096m ${argLine} 

现在我使用硬指定值:

 -Xmx1024m -XX:MaxPermSize=256m 

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

(更多信息也可以在这个问题上找到(1))

(1) – maven jacoco:不生成代码覆盖率报告

可以帮助的JVM选项:

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

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

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

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

-XX:+ShowMessageBoxOnError在JVM崩溃时显示错误对话框。

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

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

    maven-surefire-plugin   @{argLine} -XX:+HeapDumpOnOutOfMemoryError -Xmx1g -XX:HeapDumpPath=H:/dumps/ -XX:ErrorFile=H:/dumps/ -XX:+ShowMessageBoxOnError     

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

     

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

我只是删除所有maven存储库并运行maven clean install。 然后问题就消失了。