Java 9のモジュール性:Project Jigsaw、Penrose、OSGiとの積み重ね

この記事では、Java 9でJavaテクノロジーをよりモジュール化することを目的とした提案、仕様、およびプラットフォームの概要を説明します。よりモジュール化されたJavaアーキテクチャの必要性に寄与する要因について説明し、提案されたソリューションについて簡単に説明して比較します。そして、Java開発への潜在的な影響を含め、Java9で計画されている3つのモジュール性アップデートを紹介します。

なぜJavaのモジュール性が必要なのですか?

モジュール性は一般的な概念です。ソフトウェアでは、単一のモノリシックデザインとしてではなく、多数の固有のモジュールとしてプログラムまたはコンピューティングシステムを記述および実装する場合に適用されます。次に、標準化されたインターフェイスを使用して、モジュールが通信できるようにします。ソフトウェア構造の環境を個別のモジュールに分割することで、結合を最小限に抑え、アプリケーション開発を最適化し、システムの複雑さを軽減できます。

モジュール性により、プログラマーは機能テストを個別に実行し、特定のスプリントまたはプロジェクト中に並行して開発作業を行うことができます。これにより、ソフトウェア開発ライフサイクル全体の効率が向上します。

本物のモジュールのいくつかの特徴的な属性は次のとおりです。

  • 自律展開ユニット(疎結合)
  • 一貫性のある一意のID(モジュールIDとバージョン)
  • 簡単に識別および発見された要件と依存関係(標準のコンパイル時およびデプロイメント機能とメタ情報)
  • オープンでわかりやすいインターフェース(通信契約)
  • 非表示の実装の詳細(カプセル化)

モジュールを効率的に処理するように構築されたシステムは、次のことを行う必要があります。

  • モジュール性と依存関係のサポート-コンパイル時の検出
  • システムのダウンタイムなしで簡単な展開と再展開をサポートするランタイム環境でモジュールを実行します
  • 明確で堅牢な実行ライフサイクルを実装する
  • モジュールの登録と検出を容易にするための機能を提供する

オブジェクト指向、コンポーネント指向、およびサービス指向のソリューションはすべて、純粋なモジュール性を実現しようと試みてきました。ただし、各ソリューションには独自の癖があり、モジュール式の完全性を実現できません。簡単に考えてみましょう。

モジュール構造としてのJavaクラスとオブジェクト

Javaのオブジェクト指向の性質は、モジュール性の要件を満たしていませんか?結局のところ、Javaを使用したオブジェクト指向プログラミングは、一意性、データカプセル化、および疎結合を強調し、場合によっては強制します。これらのポイントは良いスタートです、Javaのオブジェクト指向フレームワークで満たされないモジュール性の要件に注意してください。オブジェクトレベルでのIDは信頼できません。インターフェイスはバージョン管理されていません。クラスはデプロイメントレベルで一意ではありません。疎結合はベストプラクティスですが、強制されません。

サードパーティの依存関係が簡単に悪用される場合、Javaでクラスを再利用することは困難です。Mavenなどのコンパイル時ツールは、この欠点に対処しようとします。依存性注入や制御の反転などの事後の言語規則や構造は、開発者がランタイム環境を制御しようとする際に役立ちます。特に厳格な規律で使用した場合、成功することがあります。残念ながら、この状況では、モジュラー環境を作成するという雑用は、独自のフレームワークの規則と構成に任されています。

Javaはまた、モジュール式のコンパイル時およびデプロイメント時のメカニズムを作成する手段として、パッケージの名前空間とスコープの可視性をミックスに追加します。しかし、これらの言語機能は、後で説明するように、簡単に回避できます。

モジュラーソリューションとしてのパッケージ

パッケージは、Javaプログラミングランドスケープに抽象化レベルを追加しようとします。これらは、固有のコーディング名前空間と構成コンテキストのための機能を提供します。ただし、残念ながら、パッケージの規則は簡単に回避され、コンパイル時のカップリングが危険な環境につながることがよくあります。

現在のJavaのモジュール性の状態(OSGiは別として、これについては後で説明します)は、ほとんどの場合、パッケージの名前空間、JavaBeansの規則、およびSpringに見られるような独自のフレームワーク構成を使用して実現されます。

JARファイルは十分にモジュール化されていませんか?

JARファイルとそれらが動作するデプロイメント環境は、他の方法で利用可能な多くのレガシーデプロイメント規則を大幅に改善します。ただし、JARファイルには、.jarマニフェストに隠されている、めったに使用されないバージョン番号を除いて、固有の一意性はありません。 JARファイルとオプションのマニフェストは、Javaランタイム環境内のモジュール性規則として使用されません。したがって、ファイル内のクラスのパッケージ名とクラスパスへの参加は、ランタイム環境にモジュール性を与えるJAR構造の唯一の部分です。

要するに、JARはモジュール化の良い試みですが、真のモジュール環境のすべての要件を満たしているわけではありません。SpringやOSGiなどのフレームワークとプラットフォームは、JAR仕様のパターンと拡張機能を使用して、非常に高性能でモジュール式のシステムを構築するための環境を提供します。ただし、時間の経過とともに、これらのツールでさえ、JAR仕様のJAR地獄の非常に不幸な副作用に屈するでしょう!

クラスパス/ JAR地獄

Javaランタイム環境で任意に複雑なJARロードメカニズムが許可されている場合、開発者はそれらがクラスパス地獄またはJAR地獄にあることを認識します。多くの構成がこの状態につながる可能性があります。

まず、Javaアプリケーション開発者がアプリケーションの更新バージョンを提供し、それを古いバージョンとまったく同じ名前のJARファイルにパッケージ化した状況を考えてみます。Javaランタイム環境には、正しいJARファイルを判別するための検証機能がありません。ランタイム環境は、最初に検出した、または多くのクラスパスルールの1つを満たすJARファイルからクラスをロードするだけです。これはせいぜい予期しない動作につながります。

JAR地獄の別のインスタンスは、2つ以上のアプリケーションまたはプロセスがサードパーティライブラリの異なるバージョンに依存している場合に発生します。標準のクラスローディング機能を使用すると、実行時に使用できるサードパーティライブラリのバージョンは1つだけになり、少なくとも1つのアプリケーションまたはプロセスでエラーが発生します。

フル機能の効率的なJavaモジュールシステムは、コードを別個の、理解しやすい、疎結合のモジュールに分離するのを容易にするはずです。依存関係を明確に指定し、厳密に実施する必要があります。他のモジュールに悪影響を与えることなくモジュールをアップグレードできる機能が利用可能である必要があります。モジュラーランタイム環境では、特定のドメインまたは垂直市場に固有の構成が可能になり、環境の起動時間とシステムフットプリントが削減されます。

Javaのモジュール性ソリューション

これまでに述べたモジュール性機能に加えて、最近の取り組みによりさらにいくつか追加されています。次の機能は、パフォーマンスを最適化し、ランタイム環境の拡張を可能にすることを目的としています。

  • セグメント化されたソースコード:個別のキャッシュされたセグメントに分割されたソースコード。各セグメントには、特定のタイプのコンパイル済みコードが含まれています。その目標には、ガベージスイープ、インクリメンタルビルド、およびメモリ管理の改善中にメソッド以外のコードをスキップすることが含まれます。
  • ビルド時の強制:名前空間、バージョン管理、依存関係などを強制するための言語構造。
  • 展開機能:モバイルデバイス環境などの特定のニーズに応じて、スケーリングされたランタイム環境を展開するためのサポート。

多くのモジュール性の仕様とフレームワークがこれらの機能を促進することを目指しており、最近、Java9の提案でトップに上がったものもあります。Javaのモジュール性の提案の概要を以下に示します。

JSR(Java Specification Request)277

現在非アクティブなのは、Java ModuleSystemであるJavaSpecification Request(JSR)277です。2005年6月にSunによって導入されました。この仕様は、OSGiと同じ領域のほとんどをカバーしていました。OSGiと同様に、JSR 277もモジュールの検出、ロード、および整合性を定義し、実行時の変更や整合性チェックをスパースにサポートします。

JSR277の欠点は次のとおりです。

  • モジュール/バンドルの動的なロードおよびアンロードはありません
  • クラス空間の一意性を実行時にチェックしません

OSGi(オープンサービスゲートウェイイニシアチブ)

1998年11月にOSGIAllianceによって導入されたOSGIプラットフォームは、Javaの正式な標準質問に対する最も広く使用されているモジュール方式の回答です。現在、リリース6では、OSGi仕様が広く受け入れられ、特に最近使用されています。

本質的に、OSGiは、モジュール、サービス、デプロイ可能なバンドルなどの形式で完全で動的なコンポーネントモデルを実装する、Javaプログラミング言語用のモジュラーシステムおよびサービスプラットフォームです。

OSGIアーキテクチャーの主要なレイヤーは次のとおりです。

  • 実行環境:バンドルが実行されるJava環境(JavaEEやJavaSEなど)。
  • モジュール:OSGiフレームワークがバンドルのモジュール式の側面を処理する場所。バンドルメタデータはここで処理されます。
  • ライフサイクル:バンドルの初期化、開始、および停止はここで行われます。
  • サービスレジストリ:バンドルが他のバンドルが検出できるようにサービスを一覧表示する場所。

OSGiの最大の欠点の1つは、ネイティブパッケージをインストールするための正式なメカニズムがないことです。

JSR 291

JSR 291は、OSGiに基づくJava SEの動的コンポーネントフレームワークであり、現在開発の最終段階にあります。この取り組みは、JSR 232によってJavaモバイル環境で行われたように、OSGiを主流のJavaに組み込むことに焦点を当てています。

JSR 294

JSR 294は、メタモジュールのシステムを定義し、プラグ可能なモジュールの実際の実施形態(バージョン、依存関係、制限など)を外部プロバイダーに委任します。この仕様では、モジュール性を促進するために、「スーパーパッケージ」や階層的に関連するモジュールなどの言語拡張機能が導入されています。厳密なカプセル化と個別のコンパイルユニットも仕様の焦点の一部です。JSR294は現在休止中です。

プロジェクトジグソー

Project Jigsawは、Java 9のモジュール性の候補として最も可能性が高いです。Jigsawは、言語構造と環境構成を使用して、JavaSE用のスケーラブルなモジュールシステムを定義しようとしています。ジグソーの主な目標は次のとおりです。

  • JavaSEランタイムとJDKを小さなデバイスにスケールダウンするのが非常に簡単になります。
  • 内部JDKAPIへのアクセスを禁止し、SecurityManager.checkPackageAccessメソッドを適用および改善することにより、JavaSEおよびJDKのセキュリティを改善します。
  • 既存のコードの最適化によるアプリケーションのパフォーマンスの向上と、先読みプログラムの最適化手法の促進。
  • ライブラリとアプリケーションを開発者が提供したモジュールとモジュラーJDKから構築できるようにすることで、JavaSE内のアプリケーション開発を簡素化します。
  • 有限のバージョン制約のセットを要求および実施する

JEP(Java拡張提案)200

2014年7月に作成されたJavaEnhancement Proposal 200は、JDKのモジュラー構造を定義しようとしています。JEP 200は、Jigsawフレームワークに基づいて構築されており、Java 8 Compact Profilesに従って、コンパイル時、ビルド時、およびデプロイ時に組み合わせることができるモジュールのセットにJDKをセグメント化するのを容易にします。これらのモジュールの組み合わせは、ジグソー準拠のモジュールで構成される縮小されたランタイム環境としてデプロイできます。

JEP 201

JEP 201は、Jigsawに基づいて、JDKソースコードをモジュールに再編成しようとしています。これらのモジュールは、モジュール境界を適用する拡張ビルドシステムによって個別のユニットとしてコンパイルできます。JEP 201は、ソー​​スコードツリーのトップレベルでモジュール境界を強調する、JDK全体のソースコード再構築スキームを提案します。

ペンローズ

Penroseは、JigsawとOSGiの間の相互運用性を管理します。具体的には、変更されたカーネルで実行されているバンドルがJigsawモジュールを利用できるように、OSGiマイクロカーネルを変更する機能を容易にします。モジュールの記述にはJSONの使用に依存しています。

Java9の計画

Java 9は、Javaのユニークなメジャーリリースです。それをユニークにしているのは、JDK全体にモジュラーコンポーネントとセグメントを導入していることです。モジュール化をサポートする主な機能は次のとおりです。

  • モジュラーソースコード:Java 9では、JREとJDKは相互運用可能なモジュールに再編成されます。これにより、小さなデバイスで実行できるスケーラブルなランタイムの作成が可能になります。
  • セグメント化されたコードキャッシュ:厳密にはモジュール式の機能ではありませんが、Java 9の新しいセグメント化されたコードキャッシュはモジュール化の精神に従い、同じ利点のいくつかを享受します。新しいコードキャッシュは、頻繁にアクセスされるコードセグメントをネイティブコードにコンパイルし、最適化されたルックアップと将来の実行のためにそれらを保存するためのインテリジェントな決定を行います。ヒープは、3つの異なるユニットにもセグメント化されます。キャッシュに永続的に保存される非メソッドコード。ライフサイクルが長くなる可能性のあるコード(「プロファイルされていないコード」と呼ばれます)。一時的なコード(「プロファイルコード」と呼ばれます)。
  • ビルド時の施行:ビルドシステムは、JEP 201を介して拡張され、モジュール境界をコンパイルして施行します。
  • デプロイメント機能:ツールは、デプロイメント時にモジュールの境界、制約、および依存関係をサポートするJigsawプロジェクト内で提供されます。

Java9早期アクセスリリース

Java 9の正確なリリース日は謎のままですが、Java.netから早期アクセスリリースをダウンロードできます。

結論として

この記事は、Java 9のモジュール性の見通しを含む、Javaプラットフォーム内のモジュール性の概要です。クラスパス地獄のような長年の問題が、よりモジュール化されたJavaアーキテクチャの必要性にどのように寄与するかを説明し、最新の新しいモジュール性のいくつかについて説明しました。 Java用に提案された機能。次に、OSGiやProject Jigsawを含む、Javaモジュール性の提案またはプラットフォームのそれぞれについて説明し、コンテキストを説明しました。

よりモジュール化されたJavaアーキテクチャの必要性は明らかです。OSGiは非常に接近していますが、現在の試みは不十分です。Java 9リリースでは、Project JigsawとOSGiがJavaのモジュラー空間の主要なプレーヤーとなり、Penroseがそれらの間の接着剤を提供する可能性があります。

このストーリー「Java9のモジュール性:Project Jigsaw、Penrose、およびOSGiとの積み重ね」は、もともとJavaWorldによって公開されました。