前提
- JenkinsはMaster-Slave環境にしている。
- Jenkins側でJUnitのテストを実施している。
- Gradleを利用。
問題
Jenkins側でUnitTestが終わらないという報告を受ける。ローカルで実行すると問題ないのとこと。JenkinsfileでTimeoutの設定をしているので、暫定対処としてそれを伸ばしてみたがそれでも解決しない。
Jenkinsのログを見ると、
Caused by:
java.lang.OutOfMemoryError: GC overhead limit exceeded
だったり、
java.lang.OutOfMemoryError: Java heap space
みたいなログが出てる。
解析
topで見たところ、以下のプロセスがCPU負荷が高い。
jenkins 23101 22201 99 18:54 ? 00:06:34 /usr/java/jdk1.8.0_144/bin/java -Djava.security.manager=worker.org.gradle.process.internal.worker.child.BootstrapSecurityManager -Dorg.gradle.native=false -javaagent:build/tmp/expandedArchives/org.jacoco.agent-0.7.10-SNAPSHOT.jar_xxxxxx/jacocoagent.jar=destfile=build/jacoco/test.exec,append=true,inclnolocationclasses=false,dumponexit=true,output=file,jmx=false -Dfile.encoding=UTF-8 -Duser.country=JP -Duser.language=ja -Duser.variant -ea -cp /xxxxx/gradle-worker.jar worker.org.gradle.process.internal.worker.GradleWorkerMain 'Gradle Test Executor 1
原因判明!
http://kitaru.hatenadiary.com/entry/2014/09/03/Java%E3%82%A2%E3%83%97%E3%83%AA%E3%81%8C%E6%9A%B4%E8%B5%B0%E3%81%97%E3%81%A6CPU%E3%81%8C%E6%AD%BB%E3%82%93%E3%81%A0%E6%99%82%E3%81%AB%E3%82%84%E3%81%A3%E3%81%9F%E3%81%93%E3%81%A8
上記を参考に、当該プロセスをjstackなりなんなりで調査すると、被疑箇所はここ。
"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00007f47f801f000 nid=0x6fcc runnable
Oh…。GC負荷か。ということはHeapのチューニングですね。
対処
ローカルでgradle test
を実行すると、heapを2G強利用していたため、上記と同様build.gradleのtestタスクを変更。
test {
maxHeapSize = "3g"
}
こんな感じで解決。20分くらいで終わるようになった。
Gradle自体はこちらによるとデフォルトでは1024MBヒープサイズを確保するようなのですが、 test タスクはビルドプロセスとは別のJVMを使うようになっており、そこにはこの制限が適用されないようです。
この話は知らなかったよ…。
参考