J'ai essayé de compiler et de tester un grand projet d'utilisation de Gradle. Le test a bien fonctionné jusqu'à leur mort inattendue. J'ai fouillé et les ressources ont dit que cela est dû à un problème de mémoire. Si je réduis le nombre de tests dans la suite, tout se passera bien.
J'ai augmenté la mémoire de 4x, j'ai augmenté le niveau de débogage, mais je ne suis toujours pas ce qui cause cela. Voici le stacktrace horriblement cryptique. La dernière ligne (défilement vers la droite) montre les paramètres de mémoire que j'ai définis.
...
...
...
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).
Ce problème semble être lié à Linux plutôt qu'à Gradle, comme indiqué dans la documentation Jenkins:
Dans les cas où la mémoire virtuelle est saturée, le destructeur de MOO (mémoire insuffisante) du noyau peut tuer de force Jenkins ou des générations individuelles. Si cela se produit sous Linux, les versions peuvent se terminer par le code de sortie 137 (numéro de signal 128 + pour SIGKILL). La sortie de la commande
dmesg
affichera des messages de journal confirmant l'action entreprise par le noyau.
https://wiki.jenkins-ci.org/display/JENKINS/I'm+getting+OutOfMemoryError
J'ai eu un problème similaire sur le serveur de DigitalOcean, ma construction de gradé a complètement échoué sur la scène test
avec un stacktrace très similaire et sans qu'un seul test soit exécuté.
La documentation Gradle indique que le démon gradle ne doit pas être exécuté dans les environnements de CI . Alors je viens d'ajouter --no-daemon
à ma commande de construction et tout a bien fonctionné. Arrêter également le démon avec ./gradlew --stop
a été utile, mais cela n’a fonctionné que pour une seule construction - la suivante a également échoué.
Ma commande de construction:
./gradlew build --no-daemon
J'ai eu le même problème, mais dans un environnement de CI où la construction sont lancés dans un conteneur docker . Dans ce cas précis, la machine virtuelle Java ne sait pas combien de mémoire elle peut utiliser et vous pouvez rencontrer ce type de problème.
Afin de permettre à la JVM de connaître la quantité de mémoire disponible, vous pouvez utiliser
gradle build -Dorg.gradle.jvmargs=-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap
et aussi le définir sur vos tâches de test:
test {
jvmArgs "-XX:+UnlockExperimentalVMOptions", "-XX:+UseCGroupMemoryLimitForHeap"
}
Ceci est une nouvelle fonctionnalité JVM introduite dans 8u131 +
voir: http://royvanrijn.com/blog/2018/05/Java-and-docker-memory-limits/
J'ai également eu le même problème sur CircleCI, mais je n'ai eu aucune chance avec tout ce qui précède. C'est ce que j'ai trouvé:
-Dorg.gradle.daemon=false
à mon CircleCI config.yml
a arrêté l'utilisation du démon, mais n'a pas résolu le problème.-Dorg.gradle.workers.max=2
à GRADLE_OPTS
, ou --max-workers 2
à la commande gradle ne semblait pas avoir beaucoup/aucun effet de ce que je pouvais voir. J'ai essayé --max-workers=2
_ au cas où, car les deux formats semblent flotter sur Google. Je me suis connecté à mon conteneur CircleCI et, dans top
, je pouvais toujours voir 3-4 Java s'arrêtaient, alors vous n'êtes pas sûr que cela fasse quelque chose?-XX:+UnlockExperimentalVMOptions
et -XX:+UseCGroupMemoryLimitForHeap
dans les arguments de la JVM et dans le test {}
configuration à l'intérieur de ma construction comme suggéré par Baptiste Mesta. Je ne vois pas comment cela pourrait fonctionner; J'aurais pensé que les multiples processus forkés ne savaient pas quelle proportion de la mémoire de conteneur utilisée par les autres processus? À moins que je ne le comprenne pas correctement.En fin de compte, je l'ai corrigé simplement en étant gentil et explicite avec les paramètres de la mémoire, plutôt qu'en utilisant la magie:
GRADLE_OPTS: -Xmx2048m -Dorg.gradle.daemon=false
test { maxHeapSize = "512m" }
Edit: vous devrez peut-être baisser, selon que d'autres processus sont en cours d'exécution ou non.
J'ai eu un problème similaire avec les agents Bamboo (fonctionnant sur Docker) exécutant Gradle 4.6. La tâche test
vient de se terminer brusquement avec
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)
Nous avons plus de 3000 tests unitaires. Dans notre cas, le problème a été résolu en utilisant forkEvery
pour limiter le nombre de classes de test exécutées par processus d'exécuteur de test, ainsi qu'en limitant l'utilisation de la mémoire:
test {
maxHeapSize '512m'
forkEvery 100
jvmArgs '-Xmx512m', '-Xms512m'
}
Semblable à la réponse de Baptiste Mesta, mais pour JDK 11, j'ai utilisé l'option JVM UseContainerSupport pour résoudre ma version de Jenkins.
./gradlew test --no-daemon -Dorg.gradle.jvmargs=-XX:+UseContainerSupport
Si vous rencontrez des problèmes avec cela sur CircleCi, où vous essayez d'exécuter Robolectric Test
J'ai trouvé la solution à mes problèmes sur leur page de documentation pour Android
https://circleci.com/docs/2.0/language-Android/
qui était simplement d'ajouter
Android {
testOptions {
unitTests {
returnDefaultValues = true
includeAndroidResources = true
all {
maxHeapSize = "1024m"
}
}
}
Si vous rencontrez toujours des problèmes de MOO, vous pouvez également limiter le nombre maximal de travailleurs pour le grade: ./gradlew test --max-workers 4
Il s’agit en fait d’un problème de mémoire. En règle générale, le conteneur Docker a une limite de mémoire de 4G; vous devez donc vous assurer que votre segment de mémoire Java ne dépasse pas cette limite, il existe peu de solutions je prends référence de Android
Ajoutez ceci à gradle.properties (changez la taille en fonction de vos besoins)
org.gradle.jvmargs=-Xmx10248m -XX:MaxPermSize=256m
Ajoutez ceci à votre build.gradle
Android.testOptions.unitTests.all { maxHeapSize = "1024m" }
ou
Android {
testOptions {
unitTests {
// Any other configurations
all {
maxHeapSize = "1024m"
}
}
}
Si vous rencontrez toujours des problèmes de MOO, vous pouvez également limiter le nombre maximal d’utilisateurs pour gradle: ./gradlew test --max-workers 4
J'espère que cela t'aides.