読者です 読者をやめる 読者になる 読者になる

kagamihogeの日記

kagamihogeの日記です。

JEP 200: The Modular JDKをテキトーに訳した

http://openjdk.java.net/jeps/200 をテキトーに訳した。

下記Updated 2014/08/08 18:21にあるとおりホットトピックなので、最新の情報については原文などを当たって頂くようお願いします。また、ビミョーな翻訳部分についても、原文を参照して頂けると幸いです。

JEP 200: The Modular JDK

Owner    Mark Reinhold
Created 2014/07/22 14:08
Updated 2014/08/08 18:21
Type    Feature
Status  Candidate
Scope   SE
Discussion  jigsaw dash dev at openjdk dot java dot net
Effort  XL
Duration    XL
Priority    1
Reviewed by Alan Bateman, Alex Buckley, Paul Sandoz
Endorsed by Brian Goetz
Issue   8051618
Depends JEP 201: Modular Source Code

Summary

JDK用のモジュール構造を定義します。モジュール構造の実装に使用するモジュールシステムに関する最低限の仮定を構築します。

Goals

JDKを、コンパイル時・ビルド時・インストール時・実行時に様々な設定で組み合わせ可能なモジュールセットに分割します。設定は以下を含みますが、これに限定されるものではありません。

  • 完全なJava SE Platform, JRE, JDKに相当する設定。
  • Java SE 8Compact Profilesとおおむね同等な設定。
  • 特定のモジュールセットと、その特定モジュールが要求するモジュールのみを含むカスタム設定。

モジュール構造の定義は、標準モジュール・Java Community Processが管理する仕様・JDK固有のモジュール、の間に明確な区分を設定します。また、Java SE Platform仕様に含めることが提案されるモジュールは、結果としてすべてのプラットフォーム実装に必須となり、そのモジュールはその他すべてのモジュールと区別されます。

Non-Goals

本JEPはここで提案されるモジュール構造の実装は担当せず、モジュールシステムの導入も行いません。実作業は関連JEPおよび必要に応じたJSRが担当します。

Motivation

Project Jigsawは、Java SE Platform用の標準モジュールシステムの設計と実装、そのシステムをプラットフォーム自身とJDKに適用すること、を目的としています。主要目的は、プラットフォーム実装のスモールデバイスへのスケールダウン簡易化・セキュリティとメンテナンス性の改善・アプリケーションパフォーマンスの改善可能化・大規模プログラミングにおけるより良いツールの開発者への提供、です。

Description

Module-system assumptions

本提案を実装するために最終的に使用されるモジュールシステムは以下の仮定に基づきます。

  1. モジュールは、Javaクラスファイル・リソース・関連ネイティブライブラリ・設定ファイル、から構成される。
  2. モジュールは名前を持つ。
  3. モジュールは、モジュール名を使用して一つ以上の他モジュールへの依存性を持つことができる。
  4. モジュールは、そのモジュールに含まれる一つ以上のAPIパッケージのすべてのpublic型をエクスポート可能です。よって、そのモジュールに依存するコードでそれらの型が使用可能ですが、任意のモジュールで使えるわけではありません。
  5. モジュールは、エクスポートする一つ以上のAPIパッケージのpublic型のモジュールセットを、モジュール名で制限可能です。(他のコードにインタフェースを暴露せずに、内部的な実装インタフェースをモジュール内で共有が可能です。)
  6. モジュールは、依存する一つ以上のモジュールがエクスポートするpublic型のすべてを、再エクスポート可能です。(エクスポートするpublic型の組み合わせを維持しつつ、時間をかけてモジュールをリファクタリング可能なことを意味します。また、 関連モジュールがエクスポートするすべてのpublic型を集約する、aggregatorモジュール定義もサポートします。)

もしモジュールシステムが最終的にこの仮定を満たさない場合、本提案はそれに応じて調整されます。

Design principles

提案されるモジュール構造は以下の規則を実装します。

  1. JCPが管理する仕様の標準モジュールは文字列"java."で始めなければならない。
  2. JDKの一部であるモジュールは文字列"jdk."で始めなければならない。
  3. あるモジュールがpublic/protectedメンバで構成される型をエクスポートし、そのメンバがさらに他モジュールの型を参照する場合、前者のモジュールは後者のpublic型を再エクスポートしなければならない。(これは明確な規則に基づいてmethod-invocationチェーンの動作を保証します。)
  4. 標準モジュールには標準・非標準APIパッケージ両方を含めることが可能です。任意の標準APIパッケージを制限無くエクスポート可能です。任意のAPIパッケージを、標準かそれ以外・制限規則付きで、標準と非標準モジュールセットにエクスポート可能です。このケース以外では非標準APIパッケージのエクスポートは禁止です。もし、あるモジュールがJava SE Platform Specificationに含めることが提案されているもの、すなわち、Java SEモジュールの場合、非SE APIパッケージのエクスポートは禁止です。
  5. 標準モジュールは一つ以上の非標準モジュールに依存可能です。非標準モジュールのpublic型の再エクスポートは禁止です。もしJava SEモジュールの場合、非SEモジュールのpublic型の再エクスポートは禁止です。
  6. 非標準モジュールは標準APIパッケージのエクスポートは禁止です。非標準モジュールは標準モジュールがエクスポートするpublic型の再エクスポートは可能です。

規則4と5から導かれる重要なことは、Java SEモジュールにのみ依存するコードは標準Java SE型にのみ依存する、それ故、Java SE Platformの全実装に移植可能です。

The module graph

JDKのモジュール構造はグラフとして可視化可能です。各モジュールはノードで、あるモジュールから別のモジュールへの有向辺が存在する場合は前者が後者に依存しています。完全なモジュールグラフは、安易に表示すると、非常に多くの辺から構成されます。ここではtransitive reductionをグラフに適用し、冗長な辺を除外しています(クリックで拡大)。

以下はモジュールグラフの説明です。

  • 標準Java SEモジュールはオレンジで、非SEモジュールはブルーの色付けがされています。
  • あるモジュールが別のモジュールに依存し、モジュールのpublic型を再エクスポートする場合、前者のモジュールから後者のモジュールへの辺は濃い色で、そうでなければ薄い色です。
  • 最下層に位置するのはjava.baseモジュールで、これにはjava.lang.Objectとjava.lang.Stringなどの中核クラス(essential classes)が含まれます。java.baseモジュールが依存するモジュールは無く、他の全モジュールはjava.baseモジュールに依存します。
  • 最上層に位置するのはjava.seモジュールで、これはJava SE Platformを構成する全モジュールを集約しています。これはaggregatorモジュールの例で、このモジュールは他モジュールのコンテンツを集約して再エクスポートするものの、自身に追加されるコンテンツはありません。java.seモジュールを含むよう設定されたランタイムシステムはSE Platformの全APIパッケージを含みます。java.seモジュールから到達可能な標準モジュール、の時かつその時に限り(if and only if:必要十分条件)、そのモジュールはJava SE Platform Specificationに含まれるように提案されます。
  • java.compact1, java.compact2, java.compact3のaggregatorモジュールはJava SE Compact Profilesを実装します。JDKのcompact3ビルドは、他のCompact Profileビルドでは依存しない非SE APIパッケージを含むので、jdk.compact3モジュールは非標準になっています。
  • 他の非標準モジュールに含まれるのは、デバッグと有用なツールAPI(例えば図中左上のjdk.jdi, jdk.jcmd, jdk.jconsole)、開発ツール(例えば図中右上のjdk.compiler, jdk.javadoc, jdk.xml.bind)、既存のjava.util.ServiceLoader convention経由で他モジュールで使用可能な各種サービスプロバイダー(例えばjdk.charsets, jdk.scripting.nashorn, jdk.crypto.ec)です。
  • java.smartcardioモジュールは標準ですがJava SE Platform Specificationの一部ではありません。名称が"java."で開始しているものの色はブルーで、java.seモジュールからは到達不能です。

モジュールグラフは実質的には新種のAPIであり、そういうものとして適用や改善が行われます。すべての非SEモジュール部分の辺を削除したjava.seモジュールのルートに位置するモジュールグラフのサブグラフがJava SE Platform Specificationに含まれるように提案されます。従ってその改善はJCPが管理します。グラフの残りの部分の改善は将来のJEPが担当します。いずれにせよ、あるモジュールを一般利用可能として指定する場合、他のAPIと同様な進化抑制が適用されます*1。そうしたモジュールの除去や非互換性の変更には、特に、あらかじめ少なくとも一つのメジャーリリースの公示が要求されます。

The module-graph definition

実際のモジュールシステムの準備が整うまでは、我々はSE PlatformとJDKのモジュール構造をシンプルなXMLドキュメントで定義します。完全なドキュメントはこちらで、例として、java.sqlモジュールの定義をコメント付きで載せます。

<module>

  <!-- モジュール名 -->
  <name>java.sql</name>

  <!-- すべてのモジュールはjava.baseに依存する。 -->
  <depend>java.base</depend>

  <!-- このモジュールはjava.logging, java.xmlに依存する。
       また、エクスポートされているAPIパッケージを再エクスポートする。 -->
  <depend re-exports="true">java.logging</depend>
  <depend re-exports="true">java.xml</depend>

  <!-- このモジュールはjava.sql, javax.sql, javax.transaction.xaパッケージを
       他モジュールにエクスポートする。 -->
  <export><name>java.sql</name></export>
  <export><name>javax.sql</name></export>
  <export><name>javax.transaction.xa</name></export>

</module>

java.security.saslモジュールの定義は制限付きのエクスポートを示しています。

<module>
  <name>java.security.sasl</name>
  <depend>java.base</depend>
  <depend>java.logging</depend>
  <export>
    <name>javax.security.sasl</name>
  </export>

  <!-- com.sun.security.sasl.util APIパッケージを
       java.security.jgssにのみエクスポートする。 -->
  <export>
    <name>com.sun.security.sasl.util</name>
    <to>java.security.jgss</to>
  </export>

</module>

linux-amd64ビルド用のfootprint metricsを含む全モジュールを表にまとめた概要はこちらです。

Open issues

現在のモジュールグラフ定義は以下にリストアップした欠点があることが知られています。これらの問題に対する解決案はグラフの構造と内容に小規模の変更を及ぼす可能性があります。

いくつかの解決案は非SE APIパッケージをエクスポートするSEモジュールを取り込み、それゆえに、上記の規則4(Principle 4)に違反します。

  • java.security.jgssがcom.sun.security.jgssをエクスポートする。
  • java.baseがjdk, jdk.netをエクスポートする。
  • java.managementがcom.sun.managementをエクスポートする。

残存課題は以下の通りです。

  • java.annotations.commonモジュールは小さくjava.xml.ws moduleでのみ使用されます。我々は前者を後者に入れ込めないかどうかを調査しています。
  • 巨大なjava.desktopモジュール内のjava.awt.datatransferパッケージはしばしば非GUIアプリケーションで使用されます。我々はそのパッケージを個別のモジュールに移動することに取り組んでいます。
  • java.managementモジュールはjava.rmiに依存しています。java.rmi自体のサイズは非自明(nontrivial in size)で組み込みデバイスのシナリオではおおむね不要です。javax.management.remote.rmi APIパッケージを個別のモジュールに移動することを検討しています。
  • jdk.attachモジュールはjdk.jvmstatに依存し、jdk.jvmstatはjava.rmiに依存しており、java.rmiは前述の問題を抱えています。我々はこの問題を解決するベストな方法を模索中です。
  • 各種のツールから成るjdk.devとjdk.runtimeモジュールは明らかに他のモジュールには属しません。これらのモジュールは最終的にはリネームかリファクタが行われます。
  • jdk.localedataモジュールは、設定に柔軟性を追加するために、最終的には複数のリージョン固有モジュールに分割されるでしょう。
  • JavaFXJDKの一部として構成されているが、まだモジュール化されていません。最終的にはjdk.javafxモジュールになるでしょう。

Testing

JDKおよびテスト実行に使用されるハーネスjtregでのユニットおよびリグレッションテストは、JDKモジュールの任意の設定がテスト可能なように、テストまたは依存するモジュールを選択した状態でのテストを許容する機能拡張が必要です。

この機能拡張における主要機能テストは、本JEPで定義しているモジュールの正しい組み合わせを保証するために、設定されたモジュールセットを検証可能でなければなりません。検証内容は、各モジュールが、期待される内容・期待されるAPIパッケージのエクスポート・モジュールが期待される依存関係を持つ、ことです。

Java SE Platform Specificationの一部となるモジュールグラフの各種機能をテストするために、JCKは機能拡張が必要です。SEモジュール名・エクスポートされるAPIパッケージ・SE APIパッケージの再エクスポートの原因となるモジュール間の依存性、が含まれます。また、プラットフォーム実装内のSEモジュールの任意の設定をテストするためにも、JCKは機能拡張が必要です。

Risks and Assumptions

上述のように、基本的なモジュールシステムの互換性について具体的で最低限の仮定*2を作成済みです。モジュールシステムは複数のJEPと一式揃いのJSRに分割されます。もしモジュールシステムが最終的にこの仮定を満たさない場合、本提案はそれに応じて調整されます。

本JEPで定義されるモジュール構造がいくつかの重要なユースケースを扱えないと判明した場合。もしクリティカルなユースケースが本JEPの初回リリース実装でサポートされない場合、我々はモジュールグラフをリファクタリングすることで、以降のリリースでそのユースケースを扱えるようにする予定です。

本JEPで定義されるモジュールグラフのJava SE機能は、レビューと標準化に向けてJava SE Platform JSR Expert Groupに最終的には提案されます。このレビューはグラフにさらなる変更を命じると思われます。

Dependences

本JEPはProject Jigsawの提案の一つ目です。これ以降のJEPとしては、以下が予定されています。

  • JDKソースコードレイアウトのモジュール化(JEP 201)
  • JDKビルドシステムが生成するバイナリイメージ構造のモジュール化
  • 関連JSRが定義するJava SE Platform向け標準モジュールシステムの実装

*1:it will be subject to the same evolutionary constraints as other APIs. 新モジュールには新規則が必要ってことなんだろうけど evolutionary constraintsって何なんだろうか。モジュールの制約に沿ったものしか受け入れなくする、って事で進化抑制ってことなんかな?

*2:yet minimal assumptionsなのだがyetが上手く訳せず