概要: Gradleのビルドを高速化するには、デーモンの仕組みを理解し、適切に管理することが重要です。本記事では、デーモンの基本から停止・削除方法、並列ビルド設定、JVMメモリ設定までを詳しく解説します。
Gradleデーモンとは?なぜビルドが速くなるのか基本を解説
Gradleデーモンの仕組みと役割
Gradleデーモンとは、バックグラウンドで長時間稼働するJVMプロセスです。GradleはJava仮想マシン上で動作するため、通常のビルド実行のたびにJVMを起動すると時間がかかります。デーモンを利用すると、一度起動したプロセスが待機し続けるため、次回以降のビルドでJVM起動を待つ必要がなくなります。
デーモンはプロジェクト情報をビルド間でキャッシュし、ファイルシステムを監視して再ビルドが必要な箇所を正確に算出します。これにより、毎回ゼロからビルドするよりも大幅に処理を省略できる仕組みです。
なお、GradleデーモンはGradle 3.0以降デフォルトで有効です。現行のGradle 9.x系では、特に設定を追加しなくても自動的にデーモンが使われます。(出典:Gradle「Gradle Daemon」ドキュメント)
デーモンによる具体的な速度改善効果
Gradle公式ドキュメントによると、デーモンを利用することで同じプロジェクトを繰り返しビルドする場合、ビルド時間を15〜75%削減できます。これはJVMの起動時間を省けるだけでなく、JVMの継続的なランタイム最適化の恩恵を受けられるためです。
特にJava仮想マシンのHotSpot最適化は、通常5〜10ビルドで安定化します。そのため、最初のビルドと10回目のビルドでは体感速度に大きな差が出ることがあります。デーモンを停止してしまうと、この最適化がリセットされる点にも注意が必要です。
IDE(統合開発環境)からGradleビルドを実行する場合も、Gradle Tooling APIが常にデーモンを使用するため、すでにデーモンの恩恵を受けています。(出典:Gradle「Gradle Daemon」ドキュメント)
デーモンのメモリ使用量と注意点
ビルド環境で最大ヒープサイズが指定されていない場合、デーモンは最大512MBのヒープを使用します。デフォルトのJVM引数は-Xmx512m -XX:MaxMetaspaceSize=384mです。これは大多数のビルドで十分なサイズとされています。
ただし、数百のサブプロジェクトや多数の設定・ソースコードを含む大規模ビルドでは、より大きなヒープが必要になる場合があります。その際はorg.gradle.jvmargsプロパティでJVM引数を指定します。
デーモンは常駐プロセスであるため、メモリリークが起きる可能性もゼロではありません。Gradleはヒープ使用量を積極的に監視し、メモリリークを検出した場合は現在のビルド完了後にデーモンを再起動します。
デーモンはGradle 3.0以降デフォルトで有効。JVM起動を省略し、15〜75%のビルド時間短縮が期待できる。デフォルトのヒープサイズは512MB。
Gradleデーモンの停止・削除方法(stop / 自動終了条件)
デーモンを停止するコマンド
デーモンを明示的に停止するには、gradle --stopコマンドを使用します。このコマンドは、実行したGradleと同じバージョンで起動された全デーモンプロセスを終了します。デーモンが原因でビルドが不安定になった場合や、トラブルシューティング時に便利です。
稼働中のデーモンを確認するにはgradle --statusコマンドを使います。稼働中のデーモンはGradleDaemonという名前で一覧表示されるため、意図しないデーモンが残っていないか確認できます。
なお、killコマンドはGradle公式の管理方法ではありません。OSのプロセス終了コマンドで直接デーモンを停止することは可能ですが、公式にはgradle --stopの使用が推奨されています。(出典:Gradle「Gradle Daemon」ドキュメント)
デーモンを無効化する設定方法
デーモンを無効化するには複数の方法があります。単一ビルドだけ無効化する場合は、コマンドラインでgradle <task> --no-daemonを指定します。
恒久的に無効化する場合は、gradle.propertiesにorg.gradle.daemon=falseを追加します。設定できる場所は以下のとおりです。
- プロジェクト直下の
gradle.properties(プロジェクト単位) - ユーザーの
~/.gradle/gradle.properties(ユーザー単位) - 環境変数
GRADLE_OPTSに-Dorg.gradle.daemon=falseを追加(環境全体)
逆に、無効化設定があっても単一ビルドでデーモンを使いたい場合は--daemonフラグで上書きできます。
デーモンの自動終了条件とカスタマイズ
デーモンは永続的に動き続けるわけではなく、一定の条件で自動停止します。公式ドキュメントによると、自動終了する条件は次の2つです。
- 利用可能なシステムメモリが少なくなったとき
- デーモンが3時間(10800000ミリ秒)アイドル状態だったとき
アイドルタイムアウトはorg.gradle.daemon.idletimeoutプロパティで変更可能です。単位はミリ秒で、例として15分に設定する場合は900000、タイムアウトを無効化して永不停止にする場合は0を指定します。(出典:Gradle「Gradle Daemon」ドキュメント)
停止にはgradle --stop、状態確認はgradle --statusを使用。デフォルトのアイドルタイムアウトは3時間で、org.gradle.daemon.idletimeoutで変更可能。
並列ビルドで高速化する方法(parallel / workers.max設定)
並列実行が効果を発揮する条件
並列実行は、独立したプロジェクトが含まれるマルチプロジェクトビルドでのみ効果を発揮します。各ワーカーが1プロジェクトを独占する仕組みのため、単一プロジェクトのビルドでは2つのタスクが並列実行されません。
単一プロジェクトで並列設定を行っても、むしろオーバーヘッドが発生する可能性があります。「parallelを有効にすれば必ず速くなる」わけではない点に注意してください。公式ドキュメントでも、デカップリング(分離)されたマルチプロジェクトビルドでのみ使用すべきとされています。
マルチプロジェクト構成の大規模なJavaプロジェクトや、複数の独立したモジュールを同時にコンパイル・テストする場合に、並列実行の恩恵を受けられます。(出典:Gradle「Build Environment」ドキュメント)
並列実行を有効化する方法
並列実行を有効化する方法は2つあります。コマンドラインで一時的に有効化する場合と、設定ファイルで恒久的に有効化する場合です。
| 設定方法 | 指定内容 | 特徴 |
|---|---|---|
| コマンドライン | gradle <task> --parallel |
単一ビルドのみ有効 |
| gradle.properties | org.gradle.parallel=true |
プロジェクト全体で恒久的に有効 |
org.gradle.parallelのデフォルトはfalseです。マルチプロジェクトビルドで並列実行を常用する場合は、gradle.propertiesに設定を追加するのが推奨されます。
なお、旧バージョンにあった--parallel-threadsオプションはGradle 3.5で削除済みです。現在は--parallelと--max-workersを使用します。
最大ワーカー数(workers.max)の設定
org.gradle.workers.maxは、Gradleが使用できる最大ワーカー数を指定するプロパティです。ワーカーとは、タスク実行スレッド、テストプロセス、フォークされた言語コンパイラなどを指します。
デフォルトはCPUプロセッサ数(JVMが利用可能なプロセッサ数)です。設定例は以下のとおりです。
gradle.propertiesを開くorg.gradle.workers.max=4を追加(数値は環境に応じて調整)- コマンドラインでは
gradle <task> --max-workers=4と指定
注意点として、org.gradle.workers.maxは並列実行自体を有効化するプロパティではありません。有効な値は正の整数(1以上)のみで、0やマイナス値はエラーになります。(出典:Gradle「Build Environment」ドキュメント)
並列実行はデカップリングされたマルチプロジェクトビルドでのみ効果あり。org.gradle.parallel=trueで有効化し、org.gradle.workers.maxはワーカー数の上限を指定する。
デーモンのJVMメモリ設定とJava Toolchainsの関係
org.gradle.jvmargsによるヒープサイズ調整
デーモンのJVMメモリを調整するには、org.gradle.jvmargsプロパティを使用します。デフォルト値は-Xmx512m -XX:MaxMetaspaceSize=384mで、大多数のビルドで十分とされています。
大規模ビルドでは、以下のようにヒープサイズを増やします。
org.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=1g -Dfile.encoding=UTF-8
この設定はデーモン(ビルドを実行するJVM)に適用されます。コマンドライン入出力のみを処理するクライアントVMには影響しません。また、org.gradle.jvmargsを変更すると、既存デーモンが再利用できず新しいデーモンが起動する場合があります。
GRADLE_OPTSとJAVA_OPTSの違い
GRADLE_OPTSはGradleクライアントVMの起動時に使用するJVM引数です。クライアントVMはコマンドライン入出力のみを処理するため、実際のビルドには影響しません。一方、JAVA_OPTSはJVMに渡すオプションです。
重要な注意点として、JAVA_OPTSとGRADLE_OPTSがorg.gradle.jvmargsと一致する場合、デーモンは一切使われずビルドがクライアントJVM内で実行されます。デーモンの恩恵を受けたい場合は、JVMメモリ設定はorg.gradle.jvmargsで行うのが基本です。
また、org.gradle.jvmargsの変更により、-Xmxや-Xmsが変わると、互換性の関係で既存デーモンが再利用できなくなります。
Java Toolchainsとの関係と互換性
Java Toolchainsは、Gradleを実行するJDKとプロジェクトのコンパイル・テストに使用するJava環境を分離する仕組みです。Gradleデーモンの互換性は、Javaバージョン、JVM属性、JVMプロパティ、Gradleバージョンの「完全一致」で判定されます。
互換性がないアイドルデーモンが存在しない場合、Gradleは新しいデーモンを起動します。例えば、Java 8ランタイムのデーモンがあるがビルドがJava 10を要求する場合や、Gradle 7.0のデーモンがあるが現在のビルドがGradle 7.4の場合、互換ではないため新しいデーモンが起動します。
これが複数のデーモンが同時に存在する理由です。各デーモンは互換性が完全に一致するビルドのみを処理します。
デーモンのJVMメモリはorg.gradle.jvmargsで調整。互換性はJavaバージョン・JVM属性・Gradleバージョンの完全一致で判定され、異なる場合は新しいデーモンが起動する。
デーモンのトラブルシューティングと互換性の注意点
デーモンが原因かどうかの切り分け
ビルドが不安定な場合、デーモンが原因かどうかを切り分けるには--no-daemonスイッチを使用します。デーモンを使わずにビルドを実行し、問題が再現するかどうかで判断できます。
問題がデーモン使用時のみ発生する場合、デーモンの状態をリセットするためにgradle --stopで停止してから再ビルドします。デーモンが不安定化する主な原因として、ビルドスクリプトやサードパーティプラグインのメモリリーク、不適切なリソース管理、グローバル状態の破損が挙げられます。
ファイルの読み書き後にクローズし忘れることが一般的な原因です。Windows OSでは、不安定化したデーモンプロセスが頻繁に停止されるという指摘もあります。(出典:Gradle「Gradle Daemon FAQ」)
メモリリークの監視とデーモンの再起動
Gradleはヒープ使用量を積極的に監視し、デーモンのメモリリークを検出します。メモリリークでヒープが枯渇した場合、デーモンは以下の動作を行います。
- 現在実行中のビルドを完了させる
- 次のビルド実行前にデーモンを再起動する
この監視機能はデフォルトで有効です。無効化する場合は、コマンドラインで-Dorg.gradle.daemon.performance.enable-monitoring=falseを指定するか、gradle.propertiesに追加します。ただし、通常は無効化する必要はありません。
監視機能により、メモリリークが発生してもビルドが突然失敗するのを防ぎ、次のビルドではクリーンな状態から実行できます。
互換性の注意点と複数デーモンの管理
デーモンの互換性は以下の値の完全一致で判定されます。
- Javaバージョン
- JVM属性(file.encoding、user.language、java.io.tmpdirなど)
- JVMプロパティ(SSL関連、JMX関連など)
- Gradleバージョン
- 最大ヒープサイズ(-Xmx)と最小ヒープサイズ(-Xms)
これらが一致しない場合、既存デーモンは再利用されず新しいデーモンが起動します。org.gradle.jvmargsを変更した場合も同様です。複数のデーモンが存在しても正常な動作ですが、不要なデーモンはgradle --stopで停止できます。
CI環境でもデーモンの使用が公式に推奨されています。ただし、一貫性を優先してデーモンを使わない選択肢も存在します。
問題切り分けは--no-daemonで。メモリリーク監視はデフォルト有効で、検出時はビルド完了後に再起動される。互換性は複数項目の完全一致で判定。
まとめ
よくある質問
Q: Gradleデーモンを停止するコマンドは?
A: 「gradle –stop」コマンドで、実行したGradleと同じバージョンで起動された全デーモンプロセスを終了できます。また、「gradle –status」で稼働中のデーモン一覧を確認できます。
Q: Gradleデーモンはデフォルトで有効ですか?
A: はい。Gradle 3.0以降、デーモンはデフォルトで有効です。そのため、特別な設定を行わなくてもデーモンが使用されます。
Q: 並列ビルドを有効にするにはどうすればよいですか?
A: gradle.propertiesに「org.gradle.parallel=true」を設定するか、コマンドラインで「–parallel」オプションを指定します。最大ワーカー数は「org.gradle.workers.max」で指定できます(デフォルトはCPU数)。
Q: Gradleデーモンのメモリを増やすにはどうすればよいですか?
A: gradle.propertiesの「org.gradle.jvmargs」にJVM引数を指定します。デフォルトは「-Xmx512m -XX:MaxMetaspaceSize=384m」ですが、大規模ビルドでは「-Xmx4g」などに増やすと効果的です。
Q: Gradleデーモンが複数起動するのはなぜですか?
A: ビルド要件(Javaバージョン、Gradleバージョン、JVMプロパティなど)が既存デーモンと完全一致しない場合、Gradleは新しいデーモンを起動します。特に「org.gradle.jvmargs」を変更すると、既存デーモンが再利用されず新しく起動されることがあります。
