BT

最新技術を追い求めるデベロッパのための情報コミュニティ

寄稿

Topics

地域を選ぶ

InfoQ ホームページ ニュース OracleがJavaモジュールシステムの状況を報告

OracleがJavaモジュールシステムの状況を報告

原文(投稿日:2015/10/12)へのリンク

OracleのJava Platform Groupチーフアーキテクトを務めるMark Reinhold氏が,モジュール化の目標は何か(そして目標としないものは何か)を中心とした報告書“State of the Module System”を発表した。その内容が既存のフレームワーク,特にOSGiと明らかに重複していることが,ユーザの間に物議を醸している。

報告書で説明されているように,さらにはJSR-376Module Systemプロジェクトのページで詳細に解説されているように,モジュールシステムとは,現在のJavaアクセシビリティモデルが抱える2つの問題に対処するためのものだ。

  • 信頼性の高い構成: コンポーネントが他のコンポーネントのクラスにアクセスしようとする場合,クラスパスを通じた現在の方法では,目的とするクラスがクラスパス上にない,あるいは複数存在する,などのエラーが起こりやすい。
  • 強力なカプセル化: ある特定のコンポーネントから他のコンポーネントに公開するクラスを制限する方法が存在しないため,すべてのクラスがパブリックに分類され,外部からアクセス可能になってしまう。

詳細は今回発表された報告書か,あるいはInfoQの以前の記事で確認できるが,要約すると,各コンポーネントを原則として(ただし必須ではない)module-info.javaという,次のような構造のモジュール記述ファイルを含んだ単一のjarファイルで表現する,ということである。

module com.foo.bar {

   requires com.foo.baz;

   exports com.foo.bar.alpha;

   exports com.foo.bar.beta;

}

ファイルはこのように,他のコンポーネントからアクセス可能なパッケージを示す1行以上のexportsと,このモジュールが必要とするモジュールを示す0行以上のrequiesで構成される。システムは,アクセスタイプが正しい可視性を持っているか(つまり,要求されるコンポーネントによってパブリックとして公開されているか)をコンパイル時に,必要なモジュールが使用可能であるかを実行時に,クラスパス全体を検査することなく評価できる方法を提供する。 OSGiとの類似性が顕著なのは,実はこの部分なのだ。

OSGiの背景

OSGiはJavaの完全な動的コンポーネントモデルを実現するモジュール化システムであり,サービスプラットフォームである。1998年に初めてJSR-8として提案され,長期のレビュー(2014年終了)の後に公開されたOSGiでは,以下のようなMANIFEST.MFファイルを添付したJARファイルとしてバンドル(モジュールに近い概念)を実現する。

Bundle-Name: Hello World

Bundle-SymbolicName: org.wikipedia.helloworld

Bundle-Description: A Hello World bundle

Bundle-ManifestVersion: 2

Bundle-Version: 1.0.0

Bundle-Activator: org.wikipedia.Activator

Export-Package: org.wikipedia.helloworld;version="1.0.0"

Import-Package: org.osgi.framework;version="1.3.0"

(Wikipediaよりサンプル引用)

フォーマットの違いこそあれ,表現しようとしているものがJava Platform Module Systemと酷似していることは明白だ。事実,Java Platform Module SystemとOSGiの類似性については,Javaをモジュール化する初期の試みであるJSR-277 “Java Module System”の頃から指摘されていた。当初Java 7での採用を目指していたJSR-277は,Javaアーティファクトの配布および実行の簡易化が目標だった。JSR-376と名称はほとんど同じだが,その取り組みは若干異なる目的を持っていた。“信頼性の高い構成”という問題の解決は課題としていたものの,“強力なカプセル化”という問題に対処する意図はなかったのだ。また,JSR-376とは対照的に,Javaアーティファクトにバージョニングモデルを導入しようとしていた。このようなOSGiの目的や提供する機能との類似性のため,提案者は当初,OSGiをソリューションとして検討していた。しかし後には,OSGiのバージョン管理機能があまりにも不足していることを理由に,その考え方を破棄している。

その後間もなくしてJSR-294が,“プログラム言語としてのJavaのモジュールサポート改善”実現を目的として作成された。同じくJava 7を目標としていた同JSRでは,カプセル化の問題を解決するためにモジュール(“スーパーパッケージ”と呼ばれる)の概念が追加された。この概念は,現在のJava Platform Module Systemプロジェクトにも通じている。JSR-277とJSR-294は,Java 7の対象から削除された2012年時点でいずれも保留(dormant)となり,その目標がJSR-376に引き継がれることになった。

その他OSGiとJavaモジュール化に関連するものとして,JSR-291 “Dynamic Component Support for Java SE” (基本的にはOSGi Service Platform Release 4の実装)がある。同JSRでは,OSGiとのスコープの違いを明確にするため,独自のJava Module SystemであるJSR-277を引き合いに出している。静的なモジュール定義をJavaで実現する意図を持つJSR-277に対して,JSR-291では,ランタイム時にロードとアンロードが可能な動的コンポーネントを重視するという違いがある。

JSR-376ではOSGiも引き合いに出して,Java Framework Module System仕様に比較してそのスコープがあまりにも大きいことから,有効なソリューションではないと結論付けている。

これらすべてを考慮すると,多くのユーザにとって,新しいモジュールシステムがOSGiと区別の付け難いものであるのも無理のないことかも知れない。結論から言ってしまえば,モジュールシステムとOSGiは,それぞれ異なる目的を持った相互補完的なシステムである。OSGiが常時実行されるアプリケーションにおいて,バンドルを動的に管理可能な環境を作り出す目的でJava上に構築されたフレームワークであるのに対して,モジュールシステムは静的に管理されるモジュールの厳格かつ容易な管理を可能にするために,Javaそのものが備える新機能なのだ。

Java Platform Module SystemとOSGiの相違点

この点の理解を深めるためInfoQは,“Enterprise OSGi in Action”の著者のひとりであるHolly Cummins氏に話を聞いた。以下に掲げた内容は,必ずしもJava Platform Module SystemとOSGiとの相違点の完全な説明ではないが,両者の目的の違いに関する基本的な理解を読者に提供するためのものだ。

Javaの新しいModule Systemは,パッケージのとクラスの可視をコンパイル時にチェックするための簡易な手段を提供する。しかしながら,OSGiのバンドルを同じ目的で使用できるかという質問に対して,氏は次のように明言した。“これには複雑な事情があるのです。”

OSGiでは,依存性はバンドルのマニフェストで表記されます。そのマニフェストを作るには,“コードファースト”と“マニフェストファースト”という,2つの基本的なアプローチがあります。コードファーストのアプローチ(bndツールやmavenバンドルプラグインで使用)では,依存性リストをコンパイルに適用するのではなく,コンパイル時にリストを生成する方法を採用しています通常の方法でコンパイルを実行した後,コンパイル時に必要とされたものに基づいて,実行時に必要なものをツーリングが特定するのです。もうひとつのアプローチであるマニフェストファーストは,EclipseのPDEツーリングで使用されています。このアプローチでは,依存性をマニフェストに宣言します。Eclipse IDEはこのマニフェストを使ってコードが参照可能なクラスを特定し,欠落している依存関係を強調表示します。PDEにはコマンドラインビルドが,MavenにはTychoというプラグインがあり,いずれもコンパイル時に依存関係の適用を行います。ただし,この可視性はOSGi自体によって適用されるのではなく,PDEに付随するツールが行うものであることに注意が必要です。PDEを使用しているチームがすべてこのようなツールを使っているとは限らないため,コンパイル時のトリックには失敗の可能性があるのです。

新しいModule Systemで重要なもうひとつの側面は,パッケージが公開するモジュールを制限できる機能を備えていることである。相互アクセスが必要な関連性を持つモジュールのセットに対して,その範囲を越えたアクセスを行わせたくない場合に有効だ。Mark Reinhold氏の報告書によると,これは次のような構文で実現されている。

module java.base {
   ...
   exports sun.reflect to
       java.corba,
       java.logging,
       java.sql,
       java.sql.rowset,
       jdk.scripting.nashorn;
}

OSGiには当初このような機能はなかった。しかし後になって追加されたことで,改めてModule Systemの目標の先を行くことになった。Holly Cummins氏によると,“バンドルにはリゾルバフックを登録して,ある特定のバンドルが公開するパッケージを制限するフィルタとして使用することができます。この同じメカニズムは,特定のメタデータを宣言したバンドルに対して適切なパッケージのみを公開することや,あるいは,火曜日だけパッケージを公開するというようなクレイジーな目的にも使えます。”

この記事に星をつける

おすすめ度
スタイル

BT