質問
クラスローダーの動作について興味深い質問があります。
質問1: クラスローダーがジャーをロードする順序は何ですか?
次の瓶と含有クラスが与えられます。
a.jar
+-com/scheffield/foo/A.class
b.jar
+-com/scheffield/foo/B.class
どのクラスがロードされますか?
質問2: ClassPathのファイルのパスと名前が一意であるのは本当ですか?
次の瓶と含有クラスが与えられます(RealWorldの例):
spring-beans-3.0.3.RELEASE.jar
+-META-INF/spring.schemas
spring-aop-3.0.3.RELEASE.jar
+-META-INF/spring.schemas
私があなたに言えることは、両方のファイルが春までにロードされるということです。そうでなければ例外が発生します(参照 この記事).
なぜ私はそれを求めているのですか:
私はいわゆる呼ばれました 大きな瓶 (Gradleのクックブックエントリ)。これは、アプリケーションクラスとその他のすべての依存関係が解凍され、大きな瓶にパケットを持つ瓶です。そして、複製されたファイルをどうするか、私は絶対にわかりません。
解決
クラスは解決されますが、クラスローダーはそれらを解決したいと考えています(これがクラスローダーアーキテクチャを持つことの全体的なポイントです)。実際に扱うほとんどのクラスローダーはのバリエーションです java.net.urlclassloader ディレクトリとジャーの検索パス(クラスパス)に基づいてクラス(およびリソース)をロードします。検索パス内の各場所はクラスのソースとして扱われ、場所は順番に検索されます。
いいえ、名前は一意ではありません。検索注文で最初に遭遇したものが使用されます。
瓶を1つの大きな瓶に組み合わせると、紛争の明確な可能性があります。効果的なClassPathの最後のソースから最初の瓶にそれらをマージするように注意している場合(したがって、以前の瓶で後の瓶をオーバーライドします)、ほぼ同じ結果が得られます。
瓶の中のマニフェストには、マージする必要がある追加の処理手順が含まれているため、おおよそ私は言います。たとえば、マニフェストにはaを含めることができます クラスパス属性 これには、クラスパスの追加の瓶が含まれます。ジャーをマージすることは可能ですが、実際の必要なクラスパスの一部を指定しているマニフェスト属性を失います。マニフェストが含まれている場合 密閉 また 署名 jarsその後、瓶の署名された部分に違反することなく、これをまったくマージすることができないかもしれません。
要約すると、瓶はこのようにマージされるようには実際には設計されていません。動作する可能性がありますが、エラーには多くの可能性がありますが、その一部は解決できません。エラーの一般的な原因の1つは、2つのJARファイルをマージし、ZIPファイルで許可されている同じパスで複数のエントリで終わることです。 Ant jarおよびzipタスクを使用すると、複数のソースをマージし、これらの種類の問題を作成できます。
本当に、代わりに、多くの瓶とソースで構成されるWebアプリを1つの戦争または耳のアーカイブにバンドルする方が良いです。それが、なぜそれらが存在するのかという点の一種です。
他のヒント
- ファイルは順序でロードされています。含まれる瓶はクラスパスに表示されます。これはクラスに適用されます。他のリソース(spring.schemaなど)をロードしている場合は、classloader.getResource(...)またはclassloader.getResources(...)を使用できます。最初のものはClassPathの最初のリソースを返し、2番目のリソースも影のリソースを返します。
- 有効なZIPアーカイブには重複エントリが含まれているとは思わない。
よろしく