web-dev-qa-db-ja.com

Java 9のオープンモジュールとは何か、およびその使用方法

openキーワード付きのモジュールとその前となしのモジュールの違いは何ですか?
例えば:

open module foo {
}

module foo {
}
27
user8693774

モジュールへのリフレクトアクセスを提供するために、Java 9が導入されましたopenキーワード。

モジュール宣言でopenキーワードを使用して、オープンモジュールを作成できます。

openモジュールは、他のモジュールへのすべてのパッケージへのリフレクトアクセスを許可します。

たとえば、Spring、Hibernateなど、リフレクションに大きく依存するフレームワークを使用する場合は、このキーワードを使用して、リフレクトアクセスを有効にすることができます。

パッケージ宣言でopensステートメントを使用して、モジュールの指定されたパッケージのリフレクトアクセスを有効にすることができます。

module foo {
    opens com.example.bar;
}

またはモジュール宣言でopenキーワードを使用:

open module foo {
}

ただし、これらを組み合わせることはできないことに注意してください。

open module foo {
    opens com.example.bar;
}

コンパイル時エラーが発生します。

それが役に立てば幸い。

19

問題の指令の背景について少し。 モジュールシステムBreaking encapsulationセクションの状態

モジュールシステムによって定義され、コンパイラと仮想マシンによって強制されるaccess-control境界に違反して、1つのモジュールがエクスポートされていないものの一部にアクセスできるようにする必要がある場合があります。別のモジュールのタイプ。これは、たとえば、内部型のホワイトボックステストを有効にしたり、サポートされていない内部APIをそれらに依存するようになったコードに公開したりするために望ましい場合があります。 --add-exportsオプションは、コンパイル時と実行時の両方でこれを行うために使用できます。

コマンドラインオプションは、たとえば次と同等です。

module Java.logging {
    exports Java.util.logging;
}

--add-exportsオプションを使用すると、指定したパッケージのパブリックタイプにアクセスできます。


その後、

さらに進んで、コアリフレクションAPIのsetAccessibleメソッドを介してすべての非パブリック要素へのアクセスを有効にする必要がある場合があります。 --add-opensオプションを使用して、実行時に、これを行うことができます。

このコマンドラインオプションは、たとえば次と同等です。

module jdk.unsupported  {
   opens Sun.misc; 
}

対照的に、通常の名前付きモジュールは、次のようにモジュール宣言で明示的に定義されています:

module foo { }

これらは explicit modules として知られています。明示的なモジュールは、たとえばexport/openパッケージへの上記のように、パッケージのディレクティブを使用して、それぞれのパブリックメンバーおよびクラスへのリフレクトアクセスを提供できます。


一方、OPENモジュールは、

が開いているパッケージを宣言しないモジュールですが、結果のモジュールはすべてのパッケージが開いているかのように扱われます

すべてのパッケージがエクスポートされたかのように、実行時にモジュールのすべてのパッケージのタイプへのアクセスを許可します。つまり、バイトコードまたはリフレクションを使用して、すべてのパッケージのクラスにアクセスできます。またはすべてのパッケージのメンバーsetAccessibleまたはMethodHandles.privateLookupInを使用したリフレクションAPIは、深いリフレクションを可能にするため、簡単に言えばすべてのパッケージのすべてのクラスのすべてのメンバーを反映​​できます。これはまた、コンパイラが許可しない理由をかなり説明しています モジュールがすでに開いている間、パッケージへの両方のオープンディレクティブ。

7
Naman