class A
によってロードされた場合、依存するClassLoaderA
すべてのクラスがによってロードされることをどこかで読んだことがあります。それは本当ですか?それが本当なら、なぜコンテキストクラスローダーを設定する必要があるのでしょうか?このように:http://blog.markturansky.com/archives/21、よろしくお願いします。A
ClassLoaderA
2 に答える
Javadocs は、クラスローダーについて次のように述べています。
ClassLoader クラスは委任モデルを使用して、クラスとリソースを検索します。ClassLoader の各インスタンスには、関連付けられた親クラス ローダーがあります。クラスまたはリソースの検索が要求されると、ClassLoader インスタンスは、クラスまたはリソース自体の検索を試行する前に、クラスまたはリソースの検索をその親クラス ローダーに委譲します。「ブートストラップ クラス ローダー」と呼ばれる仮想マシンの組み込みクラス ローダーは、それ自体は親を持ちませんが、ClassLoader インスタンスの親として機能する場合があります。
そのため、あなたの質問のステートメントは明らかに間違っています。
分離されたクラス ローダー、つまり、アプリケーション クラス ローダー チェーンに結び付けられていないクラス ローダーを作成したい場合があります。そのような場合、親が null であるクラス ローダーを作成できます。(つまり、URLClassLoader クラスのコンストラクターを確認します)
これは、この分離されたクラスローダーが特定のクラスを見つけたりロードしたりできない場合、すぐにClassNotFoundException
. これは、互いに干渉しないクラスローダーの 2 つの独立した階層を持つことができることも意味します。
-編集-
私の答えを説明します。と仮定する:
Creature
という JAR ファイルにあるというインターフェースがありますparent.jar
。Jedi
という名前の JAR ファイルにあるというクラスがありますchild.jar
。- クラス
Jedi
はインターフェイスを実装しますCreature
。
次に、現在のシステム チェーンから独立して、クラス ローダーのチェーンを作成しましょう。
ClassLoader parent = new URLClassLoader(new URL[]{parentJar.toURL()}, null);
ClassLoader child = new URLClassLoader(new URL[]{childJar.toURL()}, parent);
これで、子クラスローダーにクラスをロードするように依頼できますJedi
。
Class<?> klass1 = child.loadClass("com.star.wars.Jedi");
ここで、そのクラス ローダーをクエリすると、子クラス ローダーによってロードされたことがわかります。ここまでは順調ですね。しかし、それが実装するインターフェースはどうですか。それに依存しますが、Creature
インターフェースはその親クラスローダーでしか利用できませんでしたよね?
をリクエストするklass1.getInterfaces()[0].getClassLoader()
と、それが親クラス ローダーであることがわかります。
これは、ステートメントが次のことを証明します。
クラス A が ClassLoader A によってロードされた場合、A が依存するすべてのクラスが ClassLoader A によってロードされます。
は完全に誤りです。
あなたが読んだものは正しいです。デフォルトでは、すべてのクラスが互いに参照するだけで、最終的に同じ ClassLoader になります。あなたが提供するリンクは、反対の方法を説明しています。同じ JVM にロードされた複数のクラスは、同じ名前 (パッケージ名を含む) を持つことができますが、定義は異なります。通常、これは同じライブラリの異なるバージョンからのものである場合に発生します。ライブラリ バージョン 1 を使用するコードが常にバージョン 1 を認識し、ライブラリ バージョン 2 を使用するコードが常にバージョン 2 を認識できるようにするにはどうすればよいでしょうか? あなたが提供したリンクで説明されているように、ブートストラップ ClassLoader を介して ClassLoader 分離を使用してこれを行います。