0

クラスローダの動作について興味深い質問があります。

質問 1:クラスローダが jar をロードする順序は?

次の jar とそれを含むクラスが提供されます。

a.jar
  +-com/scheffield/foo/A.class

b.jar
  +-com/scheffield/foo/B.class

どのクラスがロードされますか?

質問 2:クラスパス内のファイルのパスと名前が一意であるというのは本当ですか?

次の jar とそれを含むクラスが提供されます (実際の例):

spring-beans-3.0.3.RELEASE.jar
  +-META-INF/spring.schemas

spring-aop-3.0.3.RELEASE.jar
  +-META-INF/spring.schemas

私が言えることは、Spring によって両方のファイルがロードされるということです。そうしないと、例外が発生します (この記事を参照)。

なぜ私はそれを求めているのですか:

いわゆるビッグジャーグラドルのクックブックエントリ)を作成しました。これは、アプリケーション クラスと他のすべての依存関係が解凍され、大きな jar にパケット化された jar です。そして、重複したファイルをどうするかは絶対にわかりません。

4

2 に答える 2

2
  1. クラスは解決されますが、クラスローダはそれらを解決したいと考えています (それがクラスローダ アーキテクチャを持つことの要点です)。実際に扱うほとんどのクラスローダーは、ディレクトリと jar の検索パス (クラスパス) に基づいてクラス (およびリソース) をロードするjava.net.URLClassLoaderのバリアントです。検索パス内の各場所はクラスのソースとして扱われ、場所は順番に検索されます。

  2. いいえ、名前は一意ではありません。検索順序で最初に見つかったものが使用されます。

jar を 1 つの大きな jar に結合すると、確実に競合が発生する可能性があります。有効なクラスパスの最後のソースから最初のソースに慎重にマージすると (したがって、後の jar を以前の jar でオーバーライドする)、ほぼ同じ結果が得られます。

jar 内のマニフェストには、マージする必要がある追加の処理命令も含まれているため、おおよそのことを言います。たとえば、マニフェストには、クラスパスに追加の jar を含むClass-Path 属性を含めることができます。jar をマージすることは可能ですが、実際に必要なクラスパスの一部を指定しているマニフェスト属性を失います。マニフェストに封印された、または署名されたjar が含まれている場合、jar の署名された部分に違反しないと、このマージをまったく実行できない可能性があります。

要約すると、jar は実際にはこの方法でマージされるようには設計されていません。動作する可能性はありますが、エラーが発生する可能性が多く、解決できないものもあります。エラーの一般的な原因の 1 つは、2 つの jar ファイルをマージして、同じパスを持つ複数のエントリを作成することです。これは、zip ファイルで許可されています。Ant jar および zip タスクを使用すると、複数のソースをマージでき、この種の問題が発生する可能性があります。

実際には、多数の jar とソースで構成される Web アプリを 1 つの WAR または EAR アーカイブにバンドルする方が適切です。それが、彼らが存在する理由の要点です。

于 2010-12-23T15:01:29.753 に答える
0
  1. ファイルは、含まれているjarがクラスパスに表示される順序でロードされています。これはクラスに適用されます。他のリソース (spring.schema など) をロードする場合は、classloader.getResource(...) または classloader.getResources(...) を使用できます。最初のものはクラスパスの最初のリソースを返し、2 番目のものもシャドウされたリソースを返します。
  2. 有効な zip アーカイブに重複したエントリが含まれているとは思いません。

よろしく

于 2010-12-23T13:48:07.323 に答える