为什么我的 Gradle 构建会因退出代码 137 而死亡?

Why are my Gradle builds dying with exit-code 137?

我一直在尝试编译和测试一个大型项目以使用 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[=11=]0(DefaultBuildExecuter.java:23)
    at org.gradle.execution.DefaultBuildExecuter.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.run(DefaultGradleLauncher.java:154)
    at org.gradle.internal.Factories.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.access0(DefaultGradleLauncher.java:32)
    at org.gradle.initialization.DefaultGradleLauncher.create(DefaultGradleLauncher.java:99)
    at org.gradle.initialization.DefaultGradleLauncher.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.call(ForwardClientInput.java:74)
    at org.gradle.launcher.daemon.server.exec.ForwardClientInput.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.run(StartBuildOrRespondWithBusy.java:50)

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

    at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54)
    at org.gradle.internal.concurrent.StoppableExecutorImpl.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[=11=]0(AsyncDispatch.java:33)
    at org.gradle.messaging.dispatch.AsyncDispatch.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).

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

In cases where virtual memory is running short the kernel OOM (Out of Memory) killer may forcibly kill Jenkins or individual builds. If this occurs on Linux you may see builds terminate with exit code 137 (128 + signal number for SIGKILL). The dmesg command output will show log messages that will confirm the action that the kernel took.

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

我在 DigitalOcean 的服务器上遇到过类似的问题,我的 gradle 构建在 test 阶段完全失败,堆栈跟踪非常相似并且没有执行任何测试。

Gradle 文档中指出 gradle 守护程序 should not be run in CI environments。所以我只是将 --no-daemon 添加到我的构建命令中,一切都运行良好。使用 ./gradlew --stop 停止守护进程也很有用,但它仅适用于单个构建 - 下一个构建也失败了。

我的构建命令:

./gradlew build --no-daemon

我遇到了同样的问题,但在 CI 环境中,构建在 docker 容器中启动。 在这种特定情况下,JVM 不知道它可以使用多少内存,您可能会遇到此类问题。

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

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

并在您的测试任务中设置它:

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

这是 8u131+ 引入的新 JVM 特性

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

我在 CircleCI 上也遇到了同样的问题,但我没有遇到上述任何问题。这是我发现的:

  • -Dorg.gradle.daemon=false 添加到我的圈子CI config.yml 阻止了守护程序的使用,但没有解决问题。
  • -Dorg.gradle.workers.max=2 添加到 GRADLE_OPTS,或将 --max-workers 2 添加到 gradle 命令似乎没有 much/any 效果,据我所知。我尝试了 --max-workers=2 以防万一,因为这两种格式似乎都在 Google 上浮动。我连接到我的 CircleCI 容器,在 top 中我仍然可以看到 3-4 个 Java 进程分叉,所以不确定这有什么作用?
  • 我也在上面的组合中尝试了 max workers = 1。
  • 按照 Baptiste Mesta 的建议,在两个 JVM args 和我构建中的 test {} 配置中尝试了 -XX:+UnlockExperimentalVMOptions-XX:+UseCGroupMemoryLimitForHeap。我不明白这是怎么回事;我本以为多个分叉进程不知道其他进程用完了多少比例的容器内存?除非我没有理解正确。

最后,我只是通过友好和明确的内存设置来修复它,而不是使用魔法:

  • 圈子CI配置:GRADLE_OPTS: -Xmx2048m -Dorg.gradle.daemon=false
  • Gradle 建造:test { maxHeapSize = "512m" }

编辑:您可能需要降低,具体取决于您是否有其他进程运行。

我在使用 Bamboo 代理(运行ning on Docker)运行ning 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'
    }

如果您在 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

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

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

这实际上是一个内存问题,一般来说,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

希望对您有所帮助。

我在 intellij 上遇到了类似的问题。我按照上述答案升级了内存,并在 gradle.properties 文件

中禁用了守护进程
org.gradle.daemon=false

Gradle 守护进程是一个长期存在的构建进程。它缓存有关文件、任务、项目结构等来自先前构建的信息。因此,使您的后续构建更加高效。默认情况下启用守护进程。但有时它会损坏,因此您可以尝试禁用守护进程。

对于我的项目,我们使用 Java 11Gradle 7.3.3

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

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