問題は、なんらかの異常な理由で、インターフェイス 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を使用することを忘れないでください。