2010-12-14 7 views
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 

私はあなたを伝えることができ、何が(this articleを参照)両方のファイルがそうでない場合、例外が発生する春によってロードされていることです。

は、なぜ私はそれを求めています:

私はいわゆる大きな瓶cookbook entry for gradle)を作りました。アプリケーションクラスと他のすべての依存関係を解凍して大きなジャーにパケット化したものです。そして、重複したファイルをどうすればいいのかは絶対にわかりません。

+0

Jarは、クラスパスに表示されている順序でロードされます。私はあなたの質問が正しいかどうかは確かではありませんが、あなたが '春の豆...瓶'と '春の瓶...'を解凍してその内容で瓶を作ったなら、 'spring.schemas'の一つがもう1つ(解凍した注文に応じて)。 – khachik

+0

OK、最初の質問に答えました。 'spring.schemas'は、ファイルを上書きしたものです。これは例外につながる。しかし、私がジャーを別々にロードしても、例外は発生しません。これはどのように可能ですか? – scheffield

+1

@khachik:BTW zipには、同じパスと名前を持つ複数のファイルを含めることができます。 :D – scheffield

答えて

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

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

大きなジャーにジャーを組み合わせると、紛争の可能性があります。効果的なクラスパスの最後のソースから最初のソースにマージすることを慎重にしている場合(これにより、後のjarを以前のjarとオーバーライドする)、ほぼ同じ結果になります。

ジャーのマニフェストには併合する必要のある追加の処理命令が含まれているため、たとえば、マニフェストには、クラスパスに追加のjarを含むClass-Path attributeを含めることができます。 jarをマージすることは可能ですが、実際に必要なクラスパスの一部を指定するマニフェスト属性は失われます。マニフェストにsealedまたはsigned jarsが含まれている場合、Jarの署名付き部分に違反することなく、このマージをまったく行うことができない場合があります。

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

本当に、多くのジャーとソースで構成されるWebアプリケーションを1つのWARまたはEARアーカイブにバンドルする方が良いでしょう。それが彼らが存在する理由の全体のポイントのようなものです。

+0

2番目の質問に対するあなたの答えは面白いです。 「最初のファイルが使用されます」と言えば、ファイルシステムから同じパスと名前を持つ1つのファイルしか取得できないため、ファイルは一意です。しかし、Springは異なるバージョン(異なるファイル)で "META-INF/spring.schemas"というファイルを読むことができます。どうやって? – scheffield

+0

@scheffield:URLClassLoaderの標準的な動作と、最も一般的に遭遇するクラスローダーの動作をちょっと限定してください。あなた自身のクラスローダーを書くなら、あなたは何でもしたいことができます。クラスローダーはツリー内に作成され、デフォルトの動作では、まずリソースを解決するように親に依頼しますが、必要に応じてローカルで解決するか、兄弟スタイルのチェックを行います(OSGiはこれを行います)。 Springの場合、クラスパス上のすべてのjarファイルを実際にスキャンして情報を取得すると思います(私はHibernateもこのようなことをすると信じています)。 –

+0

ハ!クラスローダーが追加されたすべてのファイルにアクセスできることはわかりませんでした。そのため、解決策は次のとおりです。Springには、複数の同一の名前付きファイルを認識している1つのクラスローダーが付属しています。 – scheffield

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

よろしく

関連する問題