web-dev-qa-db-ja.com

分離されたJavaプラットフォームモジュールで異なるバージョンの依存関係を使用する

MyModuleAではGuava-19を、myModuleBではguava-20を使用できると思っていました。 ジグソーモジュールには独自のクラスパスがあるためです。

MyModuleAがIterators.emptyIterator();を使用するとします。 -これはguava-20で削除され、myModuleBは新しい静的メソッドFluentIterable.of();を使用します。 -これはguava-19では利用できませんでした。残念ながら、私のテストは陰性です。コンパイル時には、問題ないように見えます。ランタイムとは対照的に、結果はNoSuchMethodErrorです。つまり、クラスローダーの最初のクラスが、どちらが失敗するかを決定します。

基礎となるカップリングによるカプセル化?私は自分の理由を見つけました。推移的な依存関係には以前と同じ問題があるため、サポートできませんでした。 ModuleAとModuleBのシグニチャでバージョンの競合があるグアバクラスが発生した場合は、それに依存します。どのクラスを使用する必要がありますか?

しかし、なぜインターネット全体で「jigsaw-モジュールシステムがクラスパス地獄を止める」と読むことができるのでしょうか。現在、同じ問題を持つ複数の小さな「クラスパスに類似」があります。それは質問というよりも不確実性です。

10
Daniel

バージョンの競合

最初の訂正:モジュールには独自のクラスパスがあると言いますが、これは正しくありません。アプリケーションのクラスパスはそのままです。それと並行して、モジュールパスが導入されましたが、基本的に同じように機能します。特に、すべてのアプリケーションクラスは同じクラスローダーによってロードされます(少なくともデフォルトでは)。

すべてのアプリケーションクラスにクラスローダーが1つしかないことも、同じクラスの2つのバージョンが存在できない理由を説明しています。クラスローディングインフラストラクチャ全体は、完全修飾クラス名でクラスを識別するのに十分であるという前提で構築されています。クラスローダー。

これにより、複数のバージョンのソリューションへの道も開かれます。以前と同様に、さまざまなクラスローダーを使用してこれを実現できます。これを行うモジュールシステムのネイティブな方法は、追加の layers を作成することです(各レイヤーには独自のローダーがあります)。

モジュール地獄?

それで、モジュールシステムはクラスパス地獄を モジュール地獄 に置き換えますか?同じライブラリの複数のバージョンは、新しいクラスローダーを作成しないとまだ不可能であるため、この根本的な問題は残ります。

一方、 分割パッケージ が原因で、少なくともコンパイルまたは起動時にエラーが発生するようになりました。これにより、プログラムが微妙に誤動作するのを防ぐことができますが、これもそれほど悪くはありません。

13
Nicolai

理論的には、アプリケーション内で異なるバージョンのsameライブラリを使用することが可能です。これを可能にする概念:layering

あなたが勉強するとき ボンネットの下のジグソー あなたはこのトピックに捧げられたセクション全体を見つけます。

基本的には、これらのレイヤーを使用してモジュールをさらにグループ化できるという考え方です。レイヤーは実行時に構築されます。そして、彼らはownクラスローダーを持っています。意味:1つのアプリケーション内で異なるバージョンのモジュールを使用することは絶対に可能である必要があります-それらは異なるレイヤーに入る必要があります。そして示されているように、この種の「複数バージョンのサポート」は、Java/jigsawに取り組んでいる人々によって活発に議論されています。これはあいまいな機能ではありません。1つの内部でさまざまなモジュールバージョンをサポートすることは意味があります

現時点での唯一の免責事項:残念ながら、「完全な」ソースコードの例はありません(私は知っています)。したがって、そのOracleプレゼンテーションにのみリンクできます。

言い換えれば、このバージョン管理の問題にはいくつかの種類の解決策がありますが、この新しいアイデアで実際のコードを体験するまでにはもっと時間がかかります。正確に言うと、さまざまなクラスローダーによって分離されるさまざまなレイヤーを作成できます。 「同じオブジェクト」がmodV1とmodV2を同時に使用できるようにするnoサポートがあります。 2つのオブジェクトのみを持つことができます。1つはmodV1を使用し、もう1つはmodV2を使用します。

(ドイツの読者は一見したいかもしれません ここ -その出版物にはレイヤーのトピックへの別の紹介が含まれています)。

Java9はそのような問題を解決しません。一言で言えば、Java 9で行われたことは、従来のアクセス修飾子(public、protected、package-private、private)をjarレベルに拡張することです。

Java 9より前は、モジュールAがモジュールBに依存している場合、BのすべてのパブリッククラスがAに対して表示されます。

Java 9を使用すると、可視性を構成できるため、クラスのサブセットのみに制限でき、各モジュールは、エクスポートするパッケージと必要なパッケージを定義できます。

これらのチェックのほとんどはコンパイラーによって行われます。

実行時perspective(classloader architecture)から、大きな変更はありません。すべてのアプリケーションモジュールは同じクラスローダーによってロードされるため、モジュラーフレームワークを使用しない限り、同じjvmで異なるバージョンの同じクラスを持つことはできません。 OSGIのように、または自分でクラスローダーを操作します。

2
Hamdi