5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Java SE 11 Silver 学習 モジュール

Posted at

はじめに

本ドキュメントで解説する内容

  • モジュール
    • モジュールの構成
    • モジュールのコンパイル
    • モジュールの実行
    • モジュール情報の確認
    • クラス/モジュールの依存関係確認
    • 非公開パッケージの一時的な公開
  • module-info.java

モジュール

  • 「モジュール」とは複数のパッケージ(主にライブラリなど)を管理する単位となる(Java9以降)
  • モジュールを利用することで、パッケージ単位でモジュール外への公開/非公開を管理できる。
  • モジュール内部でのみ利用しているパッケージが、他のコードからアクセスできないようにする用途などに利用する。
  • 標準ライブラリもモジュールとして提供されており、基本的なAPIはjava.baseとして全モジュールに提供される。
  • モジュール化されていないアプリケーションは、実行時には暗黙的に無名モジュールに属していると見做され、全モジュールを読み込み、全パッケージを公開する。

モジュールの構成

  • srcディレクトリ配下にモジュール用のディレクトリ(下記例だとmymodule)を作成する。
  • モジュール用ディレクトリにおいて、module-info.java、およびモジュールのソースを含む。
src
└── mymodule
    ├── com
    │   └── sample
    │       ├── A.java
    │       └── B.java
    └── module-info.java

モジュールのコンパイル

  • モジュール用のディレクトリに配置したmodule-info.javaを他のソースと共にコンパイル(javacコマンド)する。
    javac -d [クラスファイルの出力先ディレクトリ] [コンパイルするファイルのパス]
    
    例:
    $ javac -d src/mods/mymodule src/mymodule/module-info.java src/mymodule/com/sample/*.java
    
    src
    └── mods
        └── mymodule
            ├── com
            │   └── sample
            │       ├── A.class
            │       └── B.class
            └── module-info.class
    
  • モジュールのクラスファイルをJARファイルとしてまとめる(jarコマンド)ことも可能。
    jar --create --file=[JARファイルのパス] --main-class=[エントリーポイントクラス] -C [クラスファイルが存在するディレクトリ]
    
    例:
    $ jar --create --file=mlib/mymodule.jar --main-class=com.sample.A -C src/mods/mymodule .
    
    mlib
    └── mymodule.jar
    
  • モジュールのクラスファイルをJMODファイルとしてまとめる(jmodコマンド)ことも可能。
    jmod create --class-path [クラスファイルが存在するディレクトリ] [JMODファイルのパス]
    
    例:
    $ jmod create --class-path src/mods/mymodule mlib/mymodule.jmod
    
    mlib
    └── mymodule.jmod
    

モジュールの実行

  • javaコマンドを--module-pathおよび-mを指定して実行する。
  • メインクラスが指定されたJARファイルにアーカイブされたモジュールの場合、クラスは指定不要。
$ java --module-path [モジュールのルートディレクトリ] -m [モジュール名/モジュールのクラス]

例: 
$ java --module-path src/mods -m mymodule/com.sample.A
$ java --module-path mlib -m mymodule

モジュール情報の確認

モジュール情報(module-info.javaに定義した内容)を確認する方法は以下の2種類となる。

  1. javaコマンドを--module-pathおよび--describe-moduleを指定して実行する。
    $ java --module-path [モジュールのルートディレクトリ] --describe-module [モジュール名]
    
    例:
    $ java --module-path src/mods --describe-module mymodule
    mymodule file:///opt/src/mods/mymodule/
    requires java.base mandated
    contains com.sample
    
  2. jmodコマンドをdescribeで実行する。
    $ jmod describe [JMODファイルのパス]
    
    例:
    $ jmod describe mlib/mymodule.jmod
    mymodule
    requires java.base mandated
    contains com.sample
    

クラス/モジュールの依存関係確認

  • クラスおよびモジュールの依存関係(module-info.javaでrequired定義した内容)を確認する方法は以下の2種類となる。
  1. クラス/モジュールの依存関係を確認するにはjdepsコマンドを--list-depsを指定して実行する。
    $ jdeps --list-deps [JARファイルのパス]
    
    例:
    $ jdeps --list-deps mlib/mymodule.jar
       java.base
    
  2. モジュールの依存関係を確認するにはjavaコマンドを--show-module-resolutionで実行する。
    $ java --module-path [モジュールのルートディレクトリ] -m [モジュール名/モジュールのクラス] --show-module-resolution
    
    例:
    $ java --module-path src/mods -m mymodule/com.sample.A --show-module-resolution
    root mymodule file:///opt/src/mods/mymodule/
    java.base binds java.smartcardio jrt:/java.smartcardio
    java.base binds java.naming jrt:/java.naming
    java.base binds jdk.security.jgss jrt:/jdk.security.jgss
    ...
    

非公開パッケージの一時的な公開

  • javacコマンドを--add-exportsを指定して実行することで、非公開のパッケージを一時的に公開できる。
$ javac  javac -d [クラスファイルの出力先ディレクトリ]
  --module-path [モジュールのルートディレクトリ]
  --add-exports [対象のモジュール/公開するパッケージ=利用するモジュール]
  [コンパイルするファイルのパス]

例:
$ javac -d mods/mymodule
  --module-path mods/ \
  --add-exports mymodule/com.sample=app \  
  src/app/module-info.java src/app/com/Main.java

module-info.java

  • モジュールの公開・依存・サービス・リフレクションを定義する。
    module mymodule {
      //任意のオペレーションを記載
    }
    
  • 記載できるのは以下となる。
    • exports系: モジュール外に公開するパッケージを指定する。
    • requires系: モジュールが利用(依存)する外部モジュールを指定する。
    • uses/provides: サービス(インタフェースの実装)の利用/提供を指定する。
    • open系: リフレクションの利用を許可する。
Directive Sumary
requires 指定したモジュールをロードする(モジュール依存性)
requires static コンパイル時はモジュールが必要だが、実行時には省略可能(オプション依存性)
requires transitive̶ 推移的ロード(指定したモジュールが依存するモジュールもロードする)
exports パッケージをエクスポートする(当該パッケージのpublic型に対して、他のモジュールからアクセスできる)
exports…to エクスポートされたパッケージにアクセス可能なモジュール一覧をカンマ区切りで指定する(制限付きエクスポート)
uses モジュールが使用するサービス(インタフェース名/抽象クラス名)を指定する
provides…with サービスの実装(インタフェース定義および実装)を提供する(サービスプロバイダ)
open module定義にopenを付加することで、リフレクションによる強制アクセスを許可する(モジュール単位)
opens リフレクションによる強制アクセスを許可する(パッケージ単位)
opens…to リフレクション許可パッケージにアクセス可能なモジュール一覧をカンマ区切りで指定する(制限付きパッケージ単位)
module-info.java
[open] module <モジュール名> {
  requires <外部モジュール名>; // モジュールのロード(モジュール依存性)
  requires static <外部モジュール名>; // オプション依存性
  requires transitive <外部モジュール名> // モジュールの推移的ロード(モジュール依存性)
  exports <パッケージ名> // 制限なしエクスポート
  exports <パッケージ名> to <外部モジュール名>,<外部モジュール名> // 制限付きエクスポート
  use <インタフェース名抽象クラス名> // サービスの利用 (サービスコンシューマ)
  provides <インタフェース名抽象クラス名> with <実装クラス名> // サービスの提供 (サービスプロバイダ)
  opens <パッケージ名> // リフレクションの許可(制限なし)
  opens <パッケージ名> to <外部モジュール名>,<外部モジュール名> // リフレクションの許可(制限付き)
}
5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?