プロジェクト

全般

プロフィール

Javaモジュールシステム

Javaモジュールシステムは、JDK 9から導入されるモジュール構成です。JSR 376で仕様化がProject Jigsawとして進められています。

モジュールの概要

モジュールという新たな構成上の概念を導入しました。モジュールの中に含まれるパッケージを、モジュール外部に公開するか否かを制御できるようになっています。次に依存関係を定義できるようになっています。

また、Java SE 自体もモジュール化され、複数のモジュールの集合として定義されています。

使い方

モジュール定義ファイルとソースファイルの配置

幾つか流儀があるようです。

OpenJDK Quick-Start

OpenJDKのProject Jigsaw説明にあるディレクトリ構成です。
一つの基点の下に、ソースファイルを置くsrcディレクトリと、モジュールファイル(ビルド結果)を置くmodsディレクトリを設けます。
それぞれsrcとmodsとの下に、モジュール名に相当するサブディレクトリを作成し、その下にファイル群を置きます。

<開発作業基点>
  +-- src/
  |     +-- com.torutk.foo/
  |     |     +-- module-info.java
  |     |     +-- com/
  |     |           +-- torutk/
  |     |                 +-- foo/
  |     |                       +-- Foo.java
  |     +-- com.torutk.bar/
  |     :     +-- module-info.java
  |           +-- com/
  |                 +-- torutk/
  |                       +-- bar/
  |                             +-- Bar.java
  +-- mods/
        +-- com.torutk.foo/
        |     +-- module-info.class
        |     +-- com/
        |           +-- torutk/
        |                 +-- foo/
        |                       +-- Foo.class
        +-- com.torutk.bar/
        |     +-- module-info.class
        |     +-- com/
        |           +-- torutk/
        |                 +-- bar/
        |                       +-- Bar.class
        :

srcディレクトリの下とmodsディレクトリの下にあるピリオドを含むディレクトリ名(例、com.torutk.foo)は、Jigsawのモジュール名で、Javaのパッケージ名と必ずしも同じにする必要はありません(この例では同じになっていますが)。

櫻庭さん流儀

ITPro連載記事「最新Java情報局」のJigsaw関連記事で説明しているディレクトリ構成です。モジュールごとに独立した開発基点を持つので、チーム開発では実践的な構成です。

<開発作業基点>
  +-- modules/                          <-- 成果物(モジュール)のJARファイルを収容するディレクトリ
  |
  +-- foo/                              <-- モジュール個々の基点ディレクトリ(名前は任意)
  |     +-- bin/
  |     +-- src/
  |           +-- module-info.java
  |           +-- com/                  <-- パッケージに対応するディレクトリ
  |                 +-- torutk/
  |                       +-- foo/
  |                             +-- Foo.java
  +-- bar/
  :

modulesディレクトリ下はJARファイルを配置しています。

モジュールを収容するディレクトリ

モジュールを収容するディレクトリには、クラスファイルを配置するかJARファイルを配置することができます。

クラスファイルを置く場合、次のようにディレクトリ構成をする必要があります。

T.B.D.

操作方法

モジュールの作成(他のモジュールに依存がないもの)

まず、module-info.javaを含めて必要なソースファイルをコンパイルし、クラスファイルを生成します。

foo$ javac -d bin src/module-info.java src/com/torutk/foo/Foo.java

すると、binディレクトリ下に次のようにクラスファイルが生成されます。これは、これまでのjavacでのコンパイル結果と一緒です。

foo/
  +-- bin/
  |     +-- module-info.class
  |     +-- com/
  |           +-- torutk/
  |                 +-- foo/
  |                       +--Foo.class
  +-- src/
        +--  module-info.java
        +-- com/
              +-- torutk/
                    +-- foo/
                          +-- Foo.java

次に、jarコマンドでモジュールJARファイルを作成します。

foo$ jar --create --file=../modules/com.torutk.foo.jar -C bin .
work/
  +-- modules/
  |     +-- com.torutk.foo.jar
  +-- foo/
        +-- bin/
        :
        +-- src/

モジュールの作成(他のモジュールに依存があるもの)

まず、module-info.javaを含めて必要なソースファイルをコンパイルし、クラスファイルを生成します。その際、別のモジュールファイルを参照する必要があるので、モジュールファイルの場所を指定します。

bar$ javac -d bin -mp ../modules src/module-info.java src/com/torutk/bar/Bar.java

次に、jarコマンドでモジュールJARファイルを作成します。

bar$ jar --create --file=../modules/com.torutk.bar.jar -C bin .

実行可能なモジュールを作成する場合は、main-classの指定を追加します。

bar$ jar --create --file=../modules/com.torutk.bar.jar --main-class=com.torutk.bar.Bar -C bin .

プログラムを実行するコマンドは次です。

work$ java -mp modules -m com.torutk.bar/com.torutk.bar.Bar

main-classを指定して作成したモジュールJARファイルの場合は次のとおりモジュール名を指定して実行可能です。

work$ java -mp modules -m com.torutk.bar

既存のクラスファイル・JARファイルが必要とするモジュールを調べる

jdepsコマンドで、クラスファイルやJARファイルに必要なモジュールを確認することができます。

$ jdeps -s SimpleDemo.class 
SimpleDemo.class -> java.base
SimpleDemo.class -> javafx.controls
SimpleDemo.class -> javafx.graphics

実行に必要なモジュールの抜粋

作成したプログラムに必要なJREモジュール、ライブラリ、コマンドを抜粋します。従来はJavaプログラムを実行するにはJRE全体が必要でした。JREは、JRE 8u102 Windows 64bit版の場合で176MBを占めます。また、JDK 8でネイティブバンドルで作成したJRE込みプログラムでも166MBのサイズとなります。

Jigsawの導入により、プログラムが必要とするJREのモジュールだけを抜粋することで、実行に必要なファイル群のサイズが削減できます。

C:\work> jlink --modulepath module;"C:\Program Files\Java\jdk-9\jmods" --addmods com.torutk.bar --output bundle
 :

jlinkコマンドで、Jigsawモジュール格納パスを指定します。格納パスは、アプリケーションのモジュールを格納している ./modulesディレクトリと、JDK/JRE 9のJigsawモジュールを格納しているパスを指定します。
--outputで指定した場所に、実行に必要なファイルと抜粋したモジュールファイルが生成されます。

work/
  +-- bundle/
        +-- bin/
        |     +-- java.dll
        |     +-- java.exe
        :    :
        +-- conf/
        |     +-- net.properties
        |     +-- security/
        |     |     +-- java.policy
        |     |     +-- java.security
        |     +-- sound.properties
        +-- lib
              +-- amd64/
              |     +-- jvm.cfg
              +-- fontconfig.bfc
              +-- fontconfig.properties.src
              +-- fonts/
              |     +-- LucidaBrightDemiBold.ttf
              :     :
              +-- modules
              :

bundleの下に、javaコマンドやmodulesファイルがあります。modulesファイルにはJigsawモジュールファイルが格納されています。
今回の例では、bundleディレクトリ以下の容量は79MBとなっていました。

実行は次のコマンドです。

C:\work> bundle\bin\java -m com.torutk.bar/com.torutk.bar.Bar

抜粋したbundleディレクトリ以下を別なマシンへコピーして、上述コマンドで実行したところ、プログラムが立ち上がりました。

仕様調査

モジュール定義ファイル(module-info.java)の仕様

  1. module M.N { ... }
  2. open module M.N { ... }

1. は通常のモジュール、コンパイル時および実行時にアクセス許可を行う
2. はオープンモジュール、コンパイル時にアクセス許可を行うが実行時はすべてのパッケージが公開されたものとして扱う

  • requires <モジュール>
  • requires transitive <モジュール>
  • requires static <モジュール>
  • requires transitive static <モジュール>
  • exports <モジュール>
  • exports <モジュール> to <モジュール'>, <モジュール''>
  • opens <モジュール>
  • opens <モジュール> to <モジュール'>, <モジュール''>
  • uses <モジュール>
  • provides <モジュール> with <モジュール'>, <モジュール''>
  • requires java.base が暗黙で定義される(記述不要)
  • opens で指定したパッケージは実行時においてのみ他のモジュールからアクセス可能。すべての型およびメンバーはリフレクションを通じてアクセス可能。

参考資料

日本語

ITPro連載「最新Java情報局」(櫻庭祐一氏)

英語

仕様

OpenJDK資料

クリップボードから画像を追加 (サイズの上限: 1 GB)