IntelliJ IDEAでGradleを使ってJPMS(モジュールシステム)対応のプロジェクトを作成
JavaのビルドツールGradleが、まもなくリリースされるバージョン6.4で、Java SE 9で導入されたJava Platform Module System(略称JPMS)に対応します。Java SE 9がリリースされた2017年9月から3年近くが経過し、ようやくGradleがJPMS対応されます。
今回は、IntelliJ IDEA上でGradleをビルドツールに使うJPMS対応のプロジェクトを作成する経緯を記します。
開発環境は次です。
| 項目 | 内容 |
|---|---|
| OS | Windows 10 Pro 64bit 日本語版 |
| JDK | Liberica JDK 14 full 64bit |
| IntelliJ IDEA | Community 2020.1.1 |
| Gradle | 6.4 RC-4 |
Liberica JDK 14のインストール
Liberica JDKの提供元 Bell Software社から JDK 14.0.1 Full versionをダウンロードします。
bellsoft-jdk14.0.1+8-windows-amd64-full.zip
Full versionはJavaFXを同梱したJDKとなっています。Windows用のLiberica JDKはMSIインストーラー形式とZIP形式とが用意されています。開発環境では各種各バージョンのJDKを多数揃える(同居させる)ので、zip版をダウンロードし展開するのがよいでしょう。
IntelliJ IDEA Community版
IntelliJ IDEA Community版(無料)をインストールします。 https://www.jetbrains.com/ja-jp/idea/download/
Gradle 6.4 RC4のインストール
Gradle Build Tool - Releases を開き、[release candidates]リンクを辿り、Install Manually項の[Binary-only]をクリックすると、Gradle 6.4 RC4のバイナリzipファイルをダウンロードします。
gradle-6.4-rc-4-bin.zip
このファイルをマシン上の適切な場所(C:\Program Files\Java\gradle-6.4-rc-4)に展開しました。
IntelliJ IDEAでJDKの設定
プロジェクト作成前に、IntelliJ IDEA上でLiberica JDK 14 full のJDK定義を作成しておきます。
[File]メニュー > [Project Structure] で「Project Structure」画面を開き、左側ペインで[Program Settings] > [SDKs]を選択、中側ペインの[+]をクリックし、[Add JDK]を選択して「Select Home Directory for JDK」画面でJDKのインストールディレクトリを指定します。
「Select Home Directory for JDK」画面の右側ペインでName欄に指定したJDKに適切な名称を記入します(例:Liberica JDK 14 full)。
IntelliJ IDEAでJavaアプリケーション(単一モジュール)プロジェクト
JPMSモジュールを指定して実行するアプリケーションを作成します。今回はJPMSの定義、ビルド、実行に着目するため、依存ライブラリは使用しません。
プロジェクトの作成
IntelliJ IDEA上でGradleを使うプロジェクトを新規作成
まず、IntelliJ IDEAのプロジェクト作成機能でGradleのプロジェクトを作成します。
IntelliJ IDEAを起動、新規プロジェクト(Gradle)を作成します。なお、これで作成したプロジェクトはGradleのバージョンが古い(IntelliJ IDEA 2020.1の場合、Gradle 6.1)ので、後の手順で新しいGradleを使うよう設定を変更します。
- 「New Project」画面の左側ペインで[Gradle]を選択し、右側ペインでProject SDK欄に前の手順で定義したJDK名(例:Liberica JDK 14 full)を選択します。
- Additional Libraries and Frameworks欄は、[Java]にチェックを付けて、[Next]ボタンをクリックします。
- Name欄にプロジェクト名(例:HelloJavaFx)を記入、Location欄にプロジェクトの基点ディレクトリ1を記入
- Artifact Coordinatesの左端にある▼印をクリックし、詳細設定項目を展開します。
- GroupId欄に、成果物のグループ識別子(通常代表モジュールのパッケージ名逆順、例:com.torutk.hello)を記入します。
- ArtifactId欄に、成果物の名前(デフォルトではプロジェクト名が展開済み)を記入します。
- Version欄に、バージョン名を記入します。

IntelliJ IDEA新規プロジェクト(Gradle)の成果物定義画面
Gradleプロジェクトのディレクトリ構成
IntelliJ IDEAで作成したGradleプロジェクトのディレクトリ・ファイル構成は次です。
HelloJavaFx
│ build.gradle
│ gradlew
│ gradlew.bat
│ settings.gradle
│
├─.gradle
│ ├─6.1
│ │ │ gc.properties
│ │ │
│ │ ├─executionHistory
│ │ │ executionHistory.bin
│ │ │ executionHistory.lock
│ │ │
│ │ ├─fileChanges
│ │ │ last-build.bin
│ │ │
│ │ ├─fileHashes
│ │ │ fileHashes.bin
│ │ │ fileHashes.lock
│ │ │
│ │ └─vcsMetadata-1
│ ├─buildOutputCleanup
│ │ buildOutputCleanup.lock
│ │ cache.properties
│ │ outputFiles.bin
│ │
│ ├─checksums
│ │ checksums.lock
│ │
│ └─vcs-1
│ gc.properties
│
├─.idea
│ .gitignore
│ compiler.xml
│ gradle.xml
│ misc.xml
│ workspace.xml
│
├─gradle
│ └─wrapper
│ gradle-wrapper.jar
│ gradle-wrapper.properties
│
└─src
├─main
│ ├─java
│ └─resources
└─test
├─java
└─resources
使用するGradleをIntelliJ IDEA同梱のものから別途インストールしたものへ変更
IntelliJ IDEAの[File]メニュー > [Settings]で「Settings」画面を開き、左側ペインで[Buid, Execution, Deployment] > [Build Tools] > [Gradle]を選択、右側ペインで[Gradle Projects]領域内のUse Gradle from欄をデフォルトの'gradle-wrapper.properties' fileからSpecified locationに変更、右隣の欄にGradle 6.4 RC4のディレクトリパスを設定します。
その下のGradle JVM欄は、プロジェクトで使用するJVM(例:Liberica JDK 14 full)を選択します。
[OK]ボタンを押すと、Gradleの設定ファイルとのSyncが実行されます。
- 既存のGradleプロジェクトでGradleのバージョンを更新する場合、通常は
gradle wrapper --gradle-version 6.4-rc-4と実行して指定バージョンへ更新するようです。
build.gradleファイルの編集
IntelliJ IDEAが生成したbuild.gradle(次に示す)は、JPMS対応前のバージョン用の定義です。
plugins {
id 'java'
}
group 'com.torutk.hello'
version '0.1.0'
repositories {
mavenCentral()
}
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
}
Gradle 6.4のJPMS対応のドキュメント(以下のURL)を参照し、修正をします。 Gradle 6.4-rc-4 Release Notes
GradleプラグインをJava一般用からアプリケーション用に変更します。
plugins {
- id 'java'
+ id 'application'
}
実行クラスを含む実行可能モジュールとメインクラスを定義します。
+ application { + mainModule = 'com.torutk.hello' + mainClass = 'com.torutk.hello.MessageBoard' + }
モジュールパス推論をセットします。
version '0.1.0' + java { + modularity.inferModulePath = true + }
リポジトリ定義、依存関係定義は今回使用しないので削除しておきます。
build.gradle
修正後のbuild.gradleファイルの全体象は次です。
plugins {
id 'application'
}
group 'com.torutk.hello'
version '0.1.0'
java {
modularity.inferModulePath = true
}
application {
mainModule = 'com.torutk.hello'
mainClass = 'com.torutk.hello.MessageBoard'
}
モジュール定義
src\main\javaディレクトリの下にモジュール定義(module-info.java)を作成します。
HelloJavaFx
└─src
├─main
│ ├─java
│ │ │ module-info.java
モジュール定義の内容は次です。
module com.torutk.hello {
requires javafx.graphics;
opens com.torutk.hello to javafx.graphics;
}
- 作成するアプリケーションのモジュール名を
com.torutk.helloと定義 - アプリケーションモジュール
com.torutk.helloは、javafx.graphicsモジュールを使用(requiresの依存関係) - このアプリケーションモジュールに含む
com.torutk.helloパッケージは、javafx.graphicsモジュールに対して実行時にのみアクセスを許可(リフレクションでアクセス可能とする)
メインクラスの作成
src\main\javaディレクトリの下に、パッケージcom.torutk.helloに対応するディレクトリを作成し、その中にメインクラスを配置します。
└─src
├─main
│ ├─java
│ │ │ module-info.java
│ │ │
│ │ └─com
│ │ └─torutk
│ │ └─hello
│ │ MessageBoard.java
メインクラスの最初の雛形ソースコードは次です。
package com.torutk.hello;
import javafx.application.Application;
import javafx.stage.Stage;
public class MessageBoard extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
primaryStage.show();
}
}
- ここでは空の(真っ白な)ウィンドウを1つ表示するだけのメインクラスを記述
ビルド
では、早速ビルドしてみます。
IntelliJ IDEAのメニューからビルド
[Build]メニュー > [Build Project] を実行します。
23:40:16: Executing tasks ':classes :testClasses'... > Task :compileJava > Task :processResources NO-SOURCE > Task :classes > Task :compileTestJava NO-SOURCE > Task :processTestResources NO-SOURCE > Task :testClasses UP-TO-DATE BUILD SUCCESSFUL in 1s 1 actionable task: 1 executed 23:40:18: Tasks execution finished ':classes :testClasses'.
メニューからビルドを実行すると、Gradleのタスクのうち classes と testClasses (とその依存タスク)だけを実行しています。 ビルドの結果生成されるディレクトリ・ファイルは次です。クラスファイルのみ生成されています。
├─build │ ├─classes │ │ └─java │ │ └─main │ │ │ module-info.class │ │ │ │ │ └─com │ │ └─torutk │ │ └─hello │ │ MessageBoard.class │ │ │ ├─generated │ │ └─sources │ │ ├─annotationProcessor │ │ │ └─java │ │ │ └─main │ │ └─headers │ │ └─java │ │ └─main │ └─tmp │ └─compileJava
Gradleのbuildタスク実行
Gradleペインの中から[Tasks] > [build] > [build] を実行します。

Build結果出力は次です。
23:44:40: Executing task 'build'... > Task :compileJava > Task :processResources NO-SOURCE > Task :classes > Task :jar > Task :startScripts > Task :distTar > Task :distZip > Task :assemble > Task :compileTestJava NO-SOURCE > Task :processTestResources NO-SOURCE > Task :testClasses UP-TO-DATE > Task :test NO-SOURCE > Task :check UP-TO-DATE > Task :build BUILD SUCCESSFUL in 504ms 5 actionable tasks: 5 executed 23:44:41: Task execution finished 'build'.
先ほどのclasses、testClassesタスク以外にも、多数のタスクが実行されているのが分かります。 ビルド結果は次です。
├─build │ ├─classes │ │ └─java │ │ └─main │ │ │ module-info.class │ │ │ │ │ └─com │ │ └─torutk │ │ └─hello │ │ MessageBoard.class │ │ │ ├─distributions │ │ HelloJavaFx-0.1.0.tar │ │ HelloJavaFx-0.1.0.zip │ │ │ ├─generated │ │ └─sources │ │ ├─annotationProcessor │ │ │ └─java │ │ │ └─main │ │ └─headers │ │ └─java │ │ └─main │ ├─libs │ │ HelloJavaFx-0.1.0.jar │ │ │ ├─scripts │ │ HelloJavaFx │ │ HelloJavaFx.bat │ │ │ └─tmp │ ├─compileJava │ └─jar │ MANIFEST.MF
クラスファイルだけでなく、tar、zipファイル、jarファイル、それからシェルスクリプト/バッチファイルなども生成されています。
- distributions のtar/zipファイルには、アプリケーションのjarファイルと実行用スクリプト/バッチファイルが含まれています。
- libsのアプリケーションjarファイルは、実行可能JARファイルでかつ実行可能モジュールJARファイルとなっています。
コマンドプロンプトからjavaコマンドで実行
Liberica JDK 14にパスを通したコマンドプロンプトからアプリケーションを実行します。
D:\work\HelloJavaFx> java -p build\libs -m com.torutk.hello
- モジュールJARファイルのあるディレクトリ(build\libs)を-pオプションで指定
- 実行可能モジュール名(com.torutk.hello)を-mオプションで指定
配布イメージファイルを展開し中のバッチファイルから実行
build\distributions\HelloJavaFx-0.1.0.zip を適当な場所に展開します。
Liberica JDK 14にパスを通したコマンドプロンプトから、上述の展開した中にあるbin\HelloJavaFx.batを実行します。