web-dev-qa-db-ja.com

自動モジュールとは何ですか?

自動モジュールは、stackoverflowで何度も言及されていますが、自動モジュールの完全で簡潔な自己完結型の定義を見つけることができませんでした。

では、自動モジュールとは何ですか?すべてのパッケージをエクスポートしますか?すべてのパッケージを開きますか?他のすべてのモジュールを読み取りますか?

23
ZhekaKozlov

最初に実際の質問に答えます(「自動モジュールとは何ですか?」)が、それらが何であるかについても説明しますfor。なぜ自動モジュールがその情報なしでは動作するのかを理解するのは難しいです。

自動モジュールとは何ですか?

モジュールシステムは、モジュールパスで見つけたすべてのJARからモジュールを作成します。 モジュールのプロパティ(名前、要求、エクスポート) を定義するので簡単なモジュラーJAR(つまり、モジュール記述子を持つJAR)の場合。プレーンJAR(モジュール記述子なし)の場合、このアプローチは機能しないので、代わりにモジュールシステムは何をすべきですか? 自動モジュール と呼ばれるモジュールが自動的に作成され、3つのプロパティに対して最も安全な推測が行われます。

名前

名前の取得は、2段階のプロセスです。

  • jARがマニフェストでAutomatic-Module-Nameヘッダーを定義している場合は、モジュールの名前を定義します
  • それ以外の場合は、JARファイル名を使用して名前が決定されます

2番目のアプローチは本質的に不安定であるため、このような自動モジュールに依存するモジュールは公開しないでください。 Mavenはそれについて警告します。

必要

プレーンなJARはrequire句を表現しないので、モジュールシステムは、自動モジュールに readability graph (別名モジュールグラフ)にする他のすべてのモジュールを読み取らせます。明示的なモジュールとは異なり、自動モジュールは名前のないモジュールも読み取ります。これには、クラスパスからロードされたすべてが含まれています。この一見マイナーな詳細は非常に重要であることがわかります(以下を参照)。

ただし、自動モジュールにはいくつかの読みやすさの癖があります。

  • 最初の自動モジュールが解決されるとすぐに、他のすべてのモジュールも解決されます。つまり、モジュールパス上の単一のプレーンJARが別のモジュールによって参照されると、すべてのプレーンJARが自動モジュールとしてロードされます。
  • 自動モジュール 暗黙的に読みやすさ 他のすべての自動モジュール、つまり、モジュールの1つを読み取るモジュールは、それらすべてを読み取ります。

まとめると、いくつかのプレーンJARに依存する明示的なモジュール(つまり、非自動モジュール)が、そのうちの1つだけを必要とする(他のモジュールもモジュールパスに到達する限り)回避できるという残念な影響があります。 。

エクスポート/オープン

JARには、パブリックAPIと見なされるパッケージとそうでないパッケージの情報が含まれていないため、モジュールシステムはすべてのパッケージをエクスポートし、詳細な反映のためにそれらを開きます。

もっと

モジュールシステムはMETA-INF/servicesもスキャンし、自動モジュールにその中で指定されたサービスを提供させます。自動モジュールは、すべてのサービスの使用を許可されていると見なされます。

最後に、Main-Classマニフェストエントリも処理されるため、メインクラスがjarツールで設定された自動モジュール(つまりJava --module-path my-app.jar --module my.app)。

適切なモジュール

自動モジュールが作成されると、他のモジュールと同様に扱われます。これには、モジュールシステムが他のモジュール、たとえば分割パッケージなどをチェックすることが明示的に含まれます。

自動モジュールとはfor

モジュールを導入する理由の1つは、アプリケーションのコンパイルと起動をより信頼性の高いものにし、クラスパスで可能だったエラーをより早く見つけることでした。その重要な側面はrequires句です。

それらの信頼性を維持するために、モジュール宣言でクラスパスからロードされたすべてを除外する名前付きモジュール以外のものを要求する方法はありません。話がここで終わった場合、モジュラーJARは他のモジュラーJARにのみ依存する可能性があり、エコシステムはボトムアップからモジュール化する必要があります。

しかし、これは受け入れられないので、自動モジュールはモジュールJARが非モジュールJARに依存する手段として導入されました。そのために必要なことは、モジュールパスにプレーンJARを配置し、モジュールシステムの名前でそれを要求することだけです。それを与えます。

興味深い点は、自動モジュールは名前のないモジュールを読み取るため、クラスパスへの依存関係を残すことは現実的です(そして、私は一般的にそうすることをお勧めします)。このようにして、自動モジュールはモジュールからクラスパスへのブリッジとして機能します。

モジュールは片側に置くことができ、自動モジュールとして直接の依存関係を必要とし、間接的な依存関係はもう一方の側に残すことができます。依存関係の1つが明示的なモジュールになるたびに、モジュール側のブリッジを離れ、直接の依存関係を自動モジュールとしてブリッジに描画します。

32
Nicolai

自動モジュールは、にモジュール宣言がないため、暗黙的に定義された名前付きモジュールです。対照的に、通常の名前付きモジュールは、モジュール宣言を使用して明示的に定義されます。以降、これらをexplicit modulesと呼びます。

これらを使用する主な利点は、モジュール構造に移行されるのを待たずに、コンパイルまたは実行時にアーティファクトをモジュールとして処理できることです。

自動モジュールのモジュール名は、メインマニフェストに属性Automatic-Module-Nameがある場合、アーティファクトを含めるために使用されるJARファイルから派生します。エントリ。それ以外の場合、モジュール名は ModuleFinder によってJARファイルの名前から派生します。


自動モジュールにモジュール宣言がないという事実から派生して、すべてのモジュールまたはパッケージがそれを読み取り、開いたり、エクスポートしたりすることを通知することは事実上不可能です。

➜したがって、自動モジュールに存在するパッケージの明示的なエクスポート/オープンがないため、次のように記述されます-

..自動モジュール内のどのパッケージが他のモジュール、またはクラスパス上にあるクラスによる使用を意図されているかを判断する実用的な方法はありません。 したがって、自動モジュール内のすべてのパッケージは、実際には内部使用のみを目的としている場合でもエクスポートされると見なされます。

linkさらにリンクを引用する-

...自動モジュールが依存する可能性のある他のモジュールを事前に確認する実用的な方法はありません。したがって、モジュールグラフが解決された後、自動モジュールは、自動か明示的かにかかわらず、他のすべての名前付きモジュールを読み取るように作成されます。

proposals -自動モジュールの1つは、従来のレベルのカプセル化を提供します:すべてのパッケージが両方とも深い反射アクセスのために開かれていますおよび通常のコンパイル時および実行時アクセスに公開型にエクスポートされます。


➜さらに、自動モジュール

他のすべての自動モジュールに暗黙の可読性を付与

理由により、モジュールで複数の自動モジュールを使用している間、

..自動モジュール(x.y.z)でエクスポートされたパッケージの1つに、シグネチャが他の自動モジュール(a.b.c)で定義されたタイプを参照するタイプを含むかどうかを判断することはできません。

4
Naman

(あなたは私が言語またはJVM仕様でそれを見つけなかったので、欠けている完全な定義について正しいようです)

Javadocは、Java.lang.moduleパッケージクラスで、多くの正式な定義を提供します。

https://docs.Oracle.com/javase/9​​/docs/api/Java/lang/module/ModuleFinder.html#automatic-modules からの部分的な引用

トップレベルディレクトリにmodule-info.classがないJARファイルは、次のように自動モジュールを定義します。

  • JARファイルのメインマニフェストに属性「Automatic-Module-Name」がある場合、その値はモジュール名です。それ以外の場合、モジュール名はJARファイルの名前から派生します。

...

そして https://docs.Oracle.com/javase/9​​/docs/api/Java/lang/module/ModuleDescriptor.html から:

自動モジュールのモジュール記述子は、依存関係(Java.baseへの必須の依存関係を除く)を宣言せず、エクスポートされたパッケージや開いているパッケージを宣言しません。自動モジュールは解決中に特別な処理を行うため、構成内の他のすべてのモジュールを読み取ります。自動モジュールがJava仮想マシンでインスタンス化されると、名前のないすべてのモジュールが読み取られ、すべてのパッケージがエクスポートされて開いているかのように扱われます。

2
M Anouti