ひだまりソケットは壊れない

ソフトウェア開発に関する話を書きます。 最近は主に Android アプリ、Windows アプリ (UWP アプリ)、Java 関係です。

まじめなことを書くつもりでやっています。 適当なことは 「一角獣は夜に啼く」 に書いています。

Java 9 のモジュールシステム (JPMS; JSR 376) の概要

Java SE 9 がリリースされましたね! めでたい!

さてさて、Java SE 9 の目玉といえばやはり The Java Platform Module System (JPMS; JSR 376) ですよね! Project Jigsaw の心臓部です。

この記事では JSR 376 をさらっと読んで、JPMS の全体像をまとめておきます。 (実際の使い方などはこの記事の範囲外です。) モジュールシステムの理解への取っ掛かりとして皆さんの一助となれば幸いです。

仕様 (JSR 376) 概要

The Java Platform Module System (JPMS) の目的とその手段

JSR 376 に書かれているとおりの内容を日本語にしてます。

目標

JPMS の目標は、親しみやすく、それでいてスケーラブルなモジュールシステムを定義すること。

  • 開発者がライブラリやフレームワーク、そしてアプリケーションを開発したり使用したりする際に JPMS を使用できるように、親しみやすいもの――すなわち学び易く使い易いものでなければならない。
  • Java SE プラットフォーム自身、およびその実装をモジュール化することができるように、スケーラブルでなければならない。
手段

その目標を達成するために、2 つの基本的な機能が備わっている :

  • 信頼性の高い構成の仕組み : プログラム部品間の明確な依存関係を宣言できる (脆弱で、エラーが発生しやすいクラスパスのメカニズムを置き換える)
  • 強力なカプセル化 : どの型を他の部品からアクセスできるように公開し、どの型を公開しないか、ということをプログラム部品が宣言できる

これらの機能は、新たなプログラム部品であるモジュールによって実現される。 モジュールは Java プログラミング言語の構成物として定義され、コンパイル時と実行時の両方で一様に解釈されるものである。

JPMS の全体像

JPMS の詳細は Java 言語仕様や JVM 仕様などの中に含まれています。 JSR 376 は、それらの仕様のどこに JPMS が影響しているのかを分かりやすく表現しています。

多くのアプリケーションエンジニアが気にするのは、特に Java 言語仕様や Java API 仕様、JAR ファイル仕様といったところだと思います。 ここら辺の内容は後で少し触れます。

JSR 376 の一部ではありませんが、次のような文書も紹介されています。

また、今回のリリースに含めなかった機能等についての説明や、変更履歴についても JSR 376 には書かれています。

Java 言語仕様における JPMS

Java 言語仕様の中の JPMS に関わる部分をさらっと読んだのでメモ程度にまとめておきます。

  • 7.7 節 Module Declarations より
    • モジュール宣言は、新しい名前付きモジュール (named module) を記述する。
    • 名前付きモジュールは、他のモジュールへの依存や、他のモジュールに公開するものを記述する。
    • モジュール宣言により、モジュール名が導入される。 モジュール名は、他のモジュールとの関係を記述するのに使用される。
      • モジュール名は、1 個以上の Java 識別子をドットで連結したもの。
    • モジュールにはノーマルモジュール (normal module) とオープンモジュール (open module) の 2 種類がある。
      • ノーマルモジュールは、コンパイル時にも実行時にも export されたものしか外部コードからは扱えない。
      • オープンモジュールは、コンパイル時には export されたものしか外部コードからは扱えないが、実行時には export されていない型も外部コードから扱える。
      • リフレクションでの操作時に結構影響するっぽい。
    • モジュール宣言では、java.util.ServiceLoader によるサービスの提供あるいは利用の宣言も可能。
    • 名前付きモジュールに関連付けられていないクラスなどは、無名モジュール (unnamed module) に関連付けられる。
      • Java SE Platform は、必ず 1 つは無名モジュールをサポートしなければならない。 2 個以上サポートしても良い。
      • 無名モジュールは互換性のために存在するぽい。 (『Unnamed modules are provided by the Java SE Platform in recognition of the fact that programs developed prior to Java SE 9 could not declare named modules.』)
  • 6.1 節 より
    • モジュール名は、モジュールが export する本質的なパッケージ名に合わせるのが良い。 それが難しい場合は、著者が持つドメイン名を逆さに並べたもので始めると良い。

JAR ファイル仕様における JPMS

こちらもメモ程度に。

  • クラスパス上ではなくモジュールパス上に配置された JAR ファイルはモジュールである。
  • トップレベルに module-info.class ファイルを持つ JAR ファイルは、モジュール式 JAR ファイルである。
  • そうでない JAR ファイルは、自然発生的なモジュール (automatic module) とみなされる。
    • その場合のモジュール名は JAR ファイル名から決められ、export されるパッケージは .class ファイルから決められる。

さあ、始めましょう