1

クラス:

public interface Inter {
  ...some methods...
}

public class Impl implements Inter {
  ...some implementations...
}

問題は、なんらかの奇妙な理由で、子のInterClassLoaderを使用してインターフェースをロードし、のClassLoaderを使用して実装クラスをロードする必要があることです。Impl

この場合NoClassDefError、実装をロードしようとしている親のClassLoaderは、子のClassLoaderにロードされImplたインターフェイスを認識していないため、を取得します。Inter

子ClassLoader(コンテキストClassLoader)を使用して実装をロードする方法はありますか?または、(委任ルールを破ることによって)両方をロードするためにカスタムClassLoaderを作成する必要があるかもしれませんか?

4

2 に答える 2

3

問題は、なんらかの異常な理由で、インターフェイス Inter に子 ClassLoader をロードし、実装クラス Impl に親 ClassLoader をロードする必要があることです。

親クラスローダーに実装をロードさせながら、子クラスローダーがインターフェイスをロードする必要がある理由を理解できません。JVM が利用するクラスローディングメカニズムには、クラスのローディングを子クラスローダに延期するメカニズムがないため、これは問題を引き起こすに違いありません。JVM でクラスローディング動作を実装する通常のメカニズムは、ClassLoader クラスの API ドキュメントで定義されています。

ClassLoader クラスは委任モデルを使用して、クラスとリソースを検索します。ClassLoader の各インスタンスには、関連付けられた親クラス ローダーがあります。クラスまたはリソースの検索が要求されると、ClassLoader インスタンスは、クラスまたはリソース自体の検索を試行する前に、クラスまたはリソースの検索をその親クラス ローダーに委譲します。「ブートストラップ クラス ローダー」と呼ばれる仮想マシンの組み込みクラス ローダーは、それ自体は親を持ちませんが、ClassLoader インスタンスの親として機能する場合があります。

ClassLoader クラスを拡張してloadClass() メソッドをオーバーライドすることにより、カスタム クラスローダーを作成できます。このメソッドを拡張すると、次の 2 つの方法のいずれかでクラス ローディング委任を変更できます。

  • Parent-first : 親クラスローダーを取得して、最初にクラスをロードします。これは通常、推移的な動作です。ほとんどの親クラスローダーは、ブートストラップ クラスローダー (ルート) がクラスローダー階層に到達するまで、親へのロードを延期します。親クラスローダがクラスのロードに失敗した場合、子はそれをロードしようとします。クラスのロードに最終的に失敗すると、ClassNotFoundException がスローされます。
  • Parent-last : カスタム クラスローダーは、親に委譲する前に、最初にクラスのロードを試みます。親のクラスローダーは、子がクラスのロードに失敗した場合にのみ使用されます。

ほとんどのクラスローダは、親優先のクラスローダとして実装されています。これは、委任メカニズムがツリーを上方向にトラバースできるが、下方向にはトラバースできないためです。

クラスの読み込みと検索を階層内の子クラスローダに委任したい場合は、親のカスタム クラスローダでそれらへの参照を管理する必要があります。これは簡単ではなく、非常に例外的な状況を除いて、通常はまったく実行されません。これは、恐ろしい ClassNotFoundException と NoClassDefFoundError が非常に簡単に発生するためです。常に親に委ねられます (私が間違っていない限り、特定の Java EE コンテナーの共有ライブラリーの機能はこのように実装されています)。

そうは言っても、理想的な解決策は、インターフェイスと実装クラスの両方を親クラスローダーにロードしようとし、委任メカニズムに依存して、クラスが両方のクラスローダーに確実に見えるようにすることです。親は自分自身がロードしたクラスを「見る」ことができ、子は親のクラスを「見る」ことができます。

PS:クラスをロードおよび定義するときは、 AccessController.doPrivilegedを使用することを忘れないでください。

于 2010-08-18T09:05:44.277 に答える
0

java.lang.ClassLoaderのloadClass(String name、boolean resolve)をオーバーライドしますか?

私はあなたがしたゲスト。

ロードのデフォルトの動作では、親クラスファイルが最初にロードされ、ロード済みとしてマークされます。loadClassは、見つかった場合、ロードされたクラスを最初に取得します。これにより、オーバーライドして、カスタマイズされたクラスローダーでsuper.loadClassメソッドを呼び出さなかったのです。

于 2010-08-18T08:21:28.860 に答える