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欄に、バージョン名を記入します。
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を実行します。