これは経験豊富なプログラマーにとっては馬鹿げた質問かもしれないことは承知しています。しかし、私のプロジェクトで使用されている他のフレームワーク/jar の一部に必要なライブラリ (http クライアント) があります。ただし、それらはすべて、次のように異なるメジャー バージョンを必要とします。
httpclient-v1.jar => Required by cralwer.jar
httpclient-v2.jar => Required by restapi.jar
httpclient-v3.jar => required by foobar.jar
クラスローダーは、それらを何らかの方法で分離できるほどインテリジェントでしょうか? おそらくそうではないでしょう。クラスが 3 つの jar すべてで同じである場合、クラスローダーはこれをどのように処理しますか。どれがロードされ、その理由は?
クラスローダーは 1 つの jar だけを取得しますか、それともクラスを任意に混合しますか? たとえば、クラスが Version-1.jar からロードされた場合、同じクラスローダーからロードされた他のすべてのクラスは同じ jar に格納されますか?
この問題にどう対処しますか?
何らかの方法で jar を「required.jar」に「組み込む」ことで、 によって「1 つのユニット/パッケージ」として認識されるようにしたりClassloader
、何らかの方法でリンクしたりするトリックはありますか?
ベストアンサー1
クラスローダー関連の問題は非常に複雑な問題です。いずれにしても、いくつかの事実を念頭に置いておく必要があります。
アプリケーション内のクラスローダーは、通常、1 つ以上あります。ブートストラップ クラス ローダーは、適切なクラスローダーに委任します。新しいクラスをインスタンス化すると、より具体的なクラスローダーが呼び出されます。ロードしようとしているクラスへの参照が見つからない場合は、その親に委任し、ブートストラップ クラス ローダーに到達するまでこれを繰り返します。ロードしようとしているクラスへの参照が見つからない場合は、ClassNotFoundException が発生します。
同じクラスローダーで検索可能な同じバイナリ名を持つ 2 つのクラスがあり、どちらをロードしているかを知りたい場合は、特定のクラスローダーがクラス名を解決しようとする方法を調べることしかできません。
Java 言語仕様によれば、クラスバイナリ名には一意性の制約はありませんが、私の知る限り、クラスローダーごとに一意である必要があります。
同じバイナリ名を持つ 2 つのクラスをロードする方法を見つけましたが、これには、デフォルトの動作をオーバーライドする 2 つの異なるクラスローダーによってそれらのクラス (およびそれらのすべての依存関係) をロードすることが含まれます。大まかな例:
ClassLoader loaderA = new MyClassLoader(libPathOne);
ClassLoader loaderB = new MyClassLoader(libPathTwo);
Object1 obj1 = loaderA.loadClass("first.class.binary.name", true)
Object2 obj2 = loaderB.loadClass("second.class.binary.name", true);
クラスローダーのカスタマイズは難しい作業だといつも思っていました。可能であれば、互換性のない複数の依存関係を避けることをお勧めします。