我的Gradle构建为什么会因退出码137而失败?

81

我一直在尝试编译和测试一个大型项目,以使用Gradle。测试运行得很好,直到它们意外地停止了。我查找资料后发现这是由于内存问题引起的。如果我减少测试套件中的测试数量,它就能正常运行。

我将内存增加了4倍,并增加了调试级别,但我仍然不知道是什么原因导致的。下面是可怕的加密堆栈跟踪信息。最后一行(向右滚动)显示了我定义的内存设置。

...
...
...

1125 tests completed, 30 failed, 9 skipped
:test FAILED
:test (Thread[Daemon worker,5,main]) completed. Took 8 mins 39.684 secs.

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':test'.
> Process 'Gradle Test Executor 1' finished with non-zero exit value 137

* Try:
Run with --debug option to get more log output.

* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':test'.
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:69)
    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:46)
    at org.gradle.api.internal.tasks.execution.PostExecutionAnalysisTaskExecuter.execute(PostExecutionAnalysisTaskExecuter.java:35)
    at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:64)
    at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)
    at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:52)
    at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52)
    at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:53)
    at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
    at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:203)
    at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:185)
    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.processTask(AbstractTaskPlanExecutor.java:66)
    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.run(AbstractTaskPlanExecutor.java:50)
    at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor.process(DefaultTaskPlanExecutor.java:25)
    at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:110)
    at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.java:37)
    at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37)
    at org.gradle.execution.DefaultBuildExecuter.access$000(DefaultBuildExecuter.java:23)
    at org.gradle.execution.DefaultBuildExecuter$1.proceed(DefaultBuildExecuter.java:43)
    at org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildExecutionAction.java:32)
    at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37)
    at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:30)
    at org.gradle.initialization.DefaultGradleLauncher$4.run(DefaultGradleLauncher.java:154)
    at org.gradle.internal.Factories$1.create(Factories.java:22)
    at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:90)
    at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:52)
    at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:151)
    at org.gradle.initialization.DefaultGradleLauncher.access$200(DefaultGradleLauncher.java:32)
    at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:99)
    at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:93)
    at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:90)
    at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:62)
    at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:93)
    at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:82)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter$DefaultBuildController.run(InProcessBuildActionExecuter.java:94)
    at org.gradle.tooling.internal.provider.ExecuteBuildActionRunner.run(ExecuteBuildActionRunner.java:28)
    at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:43)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:28)
    at org.gradle.launcher.exec.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:78)
    at org.gradle.launcher.exec.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:48)
    at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:52)
    at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:37)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:26)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.exec.RequestStopIfSingleUsedDaemon.execute(RequestStopIfSingleUsedDaemon.java:34)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:74)
    at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:72)
    at org.gradle.util.Swapper.swap(Swapper.java:38)
    at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:72)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.health.DaemonHealthTracker.execute(DaemonHealthTracker.java:40)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:66)
    at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:72)
    at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.health.HintGCAfterBuild.execute(HintGCAfterBuild.java:41)
    at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
    at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:50)

BUILD FAILED    at org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(DaemonStateCoordinator.java:246)

    at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54)
    at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40)

Caused by: org.gradle.process.internal.ExecException: Process 'Gradle Test Executor 1' finished with non-zero exit value 137
Total time: 9 mins 38.624 secs
    at org.gradle.process.internal.DefaultExecHandle$ExecResultImpl.assertNormalExitValue(DefaultExecHandle.java:367)
    at org.gradle.process.internal.DefaultWorkerProcess.waitForStop(DefaultWorkerProcess.java:161)
    at org.gradle.api.internal.tasks.testing.worker.ForkingTestClassProcessor.stop(ForkingTestClassProcessor.java:86)
    at org.gradle.api.internal.tasks.testing.processors.RestartEveryNTestClassProcessor.endBatch(RestartEveryNTestClassProcessor.java:60)
    at org.gradle.api.internal.tasks.testing.processors.RestartEveryNTestClassProcessor.stop(RestartEveryNTestClassProcessor.java:54)
    at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
    at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.messaging.dispatch.FailureHandlingDispatch.dispatch(FailureHandlingDispatch.java:29)
    at org.gradle.messaging.dispatch.AsyncDispatch.dispatchMessages(AsyncDispatch.java:132)
    at org.gradle.messaging.dispatch.AsyncDispatch.access$000(AsyncDispatch.java:33)
    at org.gradle.messaging.dispatch.AsyncDispatch$1.run(AsyncDispatch.java:72)
    ... 2 more

Stopped 0 compiler daemon(s).
Received result Failure[value=org.gradle.initialization.ReportedException: org.gradle.internal.exceptions.LocationAwareException: Execution failed for task ':test'.] from daemon DaemonInfo{pid=48, address=[65adcc0f-8881-4511-b7a0-1b88c7016510 port:34390, addresses:[/0:0:0:0:0:0:0:1%lo, /127.0.0.1]], idle=false, context=DefaultDaemonContext[uid=14546872-57d6-4da6-8358-dc41cb7bb01d,javaHome=/usr/lib/jvm/java-8-oracle,daemonRegistryDir=/srv/myapplication/.gradle/daemon,pid=48,idleTimeout=120000,daemonOpts=-XX:MaxMetaspaceSize=320m,-XX:+DisableExplicitGC,-XX:+UseConcMarkSweepGC,-XX:NewSize=124m,-XX:SurvivorRatio=16,-Xms257m,-Xmx2049m,-Dfile.encoding=UTF-8,-Duser.country=US,-Duser.language=en,-Duser.variant]} (build should be done).
10个回答

44

这个问题似乎与 Gradle 文档中所述的不同,而是与 Linux 相关:

在虚拟内存不足的情况下,内核 OOM(Out of Memory)杀手可能会强制结束 Jenkins 或单个构建。如果在 Linux 上发生这种情况,您可能会看到构建以退出代码 137(128 + SIGKILL 信号编号)终止。命令 dmesg 的输出将显示日志消息,确认内核采取的操作。

https://wiki.jenkins-ci.org/display/JENKINS/I'm+getting+OutOfMemoryError


1
我认为这并不像看起来那样有用,下面还有另一个更有用的回答。这不仅仅是适用于Jenkins的问题,任何CI工具都适用。 - Jose Antonio Jimenez Saez
OOM-Kill 在某些 Linux 发行版上默认是禁用的,其中包括 Ubuntu。 - Coder Guy

36

我在DigitalOcean的服务器上遇到了类似的问题,在test阶段,gradle构建完全失败,并且没有一个测试被执行。

Gradle文档中指出,Gradle守护进程不应该在CI环境中运行。因此,我只需在我的构建命令中添加--no-daemon,一切都可以正常工作。同时使用./gradlew --stop停止守护进程也很有用,但这仅适用于单个构建 - 下一个构建仍然会失败。

我的构建命令:

./gradlew build --no-daemon

1
根据这个帖子https://stackoverflow.com/questions/44786375/sporadic-robolectric-test-failures-when-running-inside-docker-container中被接受的答案所指示的,你可能还需要一个参数; --no-daemon --max-workers 2 - Petrus
从6.6.1版本开始,在CI中推荐使用守护进程。https://docs.gradle.org/6.6.1/userguide/gradle_daemon.html#sec:disabling_the_daemon - jersub
@jersub 感谢您的更新!我想我的评论仍然相关,因为原始文档中说:“但是,如果您怀疑 Daemon 会使您的 CI 构建不稳定,您可以禁用它,以便每次构建都使用全新的运行时,因为该运行时与任何先前的构建完全隔离。” - Roman Golyshev

12

我在CircleCI上也遇到了同样的问题,但是上述任何方法都没有奏效。这是我找到的:

  • -Dorg.gradle.daemon=false 添加到我的CircleCI config.yml 中可以停止使用守护程序,但并没有解决问题。
  • -Dorg.gradle.workers.max=2 添加到 GRADLE_OPTS 或者将 --max-workers 2 添加到gradle命令中似乎没有很大/任何影响,从我所看到的情况来看。我尝试了--max-workers=2,因为这两种格式似乎都在Google上出现过。我连接到我的CircleCI容器,在top中我仍然可以看到3-4个Java进程在分叉,所以不确定这是否起到了作用?
  • 我还尝试了在上述组合中设置最大工人数=1。
  • 尝试在JVM args中和在构建内的test {}配置中使用 -XX:+UnlockExperimentalVMOptions-XX:+UseCGroupMemoryLimitForHeap,如Baptiste Mesta所建议的那样。我不知道这怎么可能起作用;我认为多个分叉进程不知道其他进程使用了容器内存的比例? 除非我理解有误。

最后,我只是通过设置内存设置来明确和清晰地解决了它,而不是使用魔法:

  • Circle CI配置:GRADLE_OPTS: -Xmx2048m -Dorg.gradle.daemon=false
  • Gradle构建: test { maxHeapSize = "512m" }
  • 编辑:根据您是否运行其他进程,可能需要将值设置得更低。


    2
    这对我的Android项目和Circle CI有效,将environment: GRADLE_OPTS: -Xmx2048m -Dorg.gradle.daemon=false添加到Circle CI的config.yml文件中。- 谢谢 - superus8r
    1
    使用付费账户中提供的升级后的机器(资源类别),通常可以解决这个问题。 - Oded Regev
    1
    我不知道为什么这个解决方案能运行。Gradle文档(https://docs.gradle.org/current/userguide/build_environment.html#sec:gradle_environment_variables)指出,实际构建是由Gradle守护进程运行的,该守护进程不受“GRADLE_OPTS”的影响。但是,在“配置JVM内存”(https://docs.gradle.org/current/userguide/build_environment.html#sec:configuring_jvm_memory)下有一个说明,如果禁用守护进程(您已经这样做了)且客户端VM具有相同的设置(我怎么知道?),则构建将不在单独的VM分支中运行,而是在客户端VM本身中运行。 - Erik

    12

    我曾经在一个CI环境中遇到了同样的问题,其中构建是在docker容器中启动的。 在这种特殊情况下,JVM不知道可以使用多少内存,您可能会遇到这种类型的问题。

    为了让JVM知道有多少可用内存,您可以使用

    gradle build -Dorg.gradle.jvmargs=-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap

    并且还要在测试任务中设置它:

    test {
      jvmArgs "-XX:+UnlockExperimentalVMOptions", "-XX:+UseCGroupMemoryLimitForHeap"
    }
    

    这是JVM 8u131+引入的新功能。

    请参阅:http://royvanrijn.com/blog/2018/05/java-and-docker-memory-limits/


    在CircleCi中,将测试JVM参数简单地添加到我的Gradle中就可以了,不需要更改命令。 - Brooks DuBois
    与Java10及更高版本无关。 - fyrkov

    6

    类似Baptiste Mesta的回答,但对于JDK 11,我使用了UseContainerSupport JVM选项来解决我的Jenkins构建问题。

    ./gradlew test --no-daemon -Dorg.gradle.jvmargs=-XX:+UseContainerSupport
    

    4
    UseContainerSupport 默认启用了吗? - fyrkov
    就我个人而言,我需要使用 UseContainerSupport 才能使其正常工作。 - Reid Mac

    3

    我曾经遇到过类似的问题,使用Docker运行的Bamboo代理在运行Gradle 4.6时,test任务会突然终止。

        build   27-Dec-2018 22:00:20    22:00:20.018 [DEBUG] [org.gradle.process.internal.DefaultExecHandle] Process 'Gradle Test Executor 1' finished with exit value 137 (state: FAILED)
    

    我们有超过3000个单元测试。在我们的情况下,使用forkEvery限制每个测试执行器进程运行的测试类数量,并限制内存使用量来解决了这个问题:
        test {
            maxHeapSize '512m'
            forkEvery 100
            jvmArgs '-Xmx512m', '-Xms512m'
        }
    

    1
    我应该在哪里添加test{}选项?我尝试在我的build.gradle文件中添加,但运行失败了。 - Chris F

    1
    这实际上是一个内存问题。一般来说,Docker容器的内存限制为4G,因此您需要注意Java堆不要超过该限制。有几种解决方法,我参考了Android的内容。
    1. 将以下内容添加到gradle.properties中(根据需要更改大小):
    org.gradle.jvmargs=-Xmx10248m -XX:MaxPermSize=256m
    2. 将以下内容添加到build.gradle中:
    android.testOptions.unitTests.all { maxHeapSize = "1024m" }
    或者
    android {
        testOptions {
            unitTests {
                // Any other configurations
                all {
                    maxHeapSize = "1024m"
                }
            }
        }
    

    如果你仍然遇到OOM问题,你也可以限制gradle的最大工作线程数:./gradlew test --max-workers 4 希望这能有所帮助。

    10248m是10G吗? - Phil

    0

    在我的项目中,我们正在使用Java 11Gradle 7.3.3

    我通过增加堆大小并在Gradle测试任务中添加jvm参数来解决了这个问题。

    test {
       useJUnitPlatform()
       maxHeapSize("2048m")
       jvmArgs "-XX:+UnlockExperimentalVMOptions"
    }
    

    0

    我在IntelliJ上遇到了类似的问题。我按照上面的回答升级了内存,并在gradle.properties文件中禁用了守护进程。

    org.gradle.daemon=false
    

    Gradle Daemon是一个长期运行的构建过程。它会缓存有关文件、任务、项目结构等的信息,以便从上一次构建中获取。因此,可以使您的后续构建更加高效。Daemon进程默认启用。但有时会出现损坏,因此您可以尝试禁用Daemon进程。


    0

    如果您在CircleCi上遇到问题,尝试运行Robolectric测试

    我在他们的Android文档页面上找到了解决方案

    https://circleci.com/docs/2.0/language-android/

    这只是简单地添加

    android {
        testOptions {
            unitTests {
                returnDefaultValues = true
                includeAndroidResources = true
    
                all {
                    maxHeapSize = "1024m"
                }
            }
        }
    

    如果您仍然遇到OOM问题,您还可以限制gradle的最大工作线程数:./gradlew test --max-workers 4


    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接