小さなイントロ
ご存じのとおり、Java はデフォルトでブートストラップ クラスローダーとシステム クラスローダーを使用します。1 つ目はブートストラップ クラス (そのクラスパスには rt.jar などのアーティファクトが含まれます) をロードし、2 つ目はアプリケーションのクラスパスを保持します。通常、クラスパスは、環境変数で定義されるか、-cp
引数を使用して JVM 開始時に指定されます。
答え
クラスは、次の 2 つのいずれかが発生した場合にのみcom.example.SomeClass
、カスタム クラスローダによってロードされます。起動時にカスタム クラスローダをシステム クラスローダとして使用するように定義するか、実行時にカスタム クラスローダを介してクラスを明示的にロードします。Custom
各オプションについてもう少し詳しく:
アプリケーションの起動時: JVM インスタンスの起動時に、Java のデフォルトのシステム クラス ローダーを使用する代わりに独自のクラス ローダーを使用するように定義できます。これを行うには、次の環境変数を定義して java を呼び出すだけです。
-Djava.system.class.loader=my.tests.classloaders.Custom
この場合、その JVM インスタンス内のアプリケーションのすべてのクラスが実際にCustom
クラス ローダーによってロードされます。
実行時: 実行時に、カスタム クラス ローダーを使用してクラスをロードできます。これは、カスタム クラス ローダーのインスタンスを作成し、そこからクラスをロードすることで実現されます。
ClassLoader classloader = new CustomClassLoader();
Class someClass = classloader.loadClass("com.example.SomeClass");
@Noofizが彼の答えで言ったように、1つのクラスをロードすると、必要でまだロードされていないすべての参照クラスが、関連するクラスローダーを介してロードされます。そのため、カスタム クラス ローダーを使用して 1 つのクラスをロードすると、参照されているすべてのクラスもそれを介してロードされます。すべてのクラスをロードするときは、好きなことをしたり、ロードされているクラスをログに記録したり、親クラスローダーに委譲したり、自分でクラスをロードしたりできます...
追加情報
通常、カスタム クラス ローダーを実装する最善の方法は、前述の委任モデルを使用することです。これは、クラスが実際にはクラスのバイトコードだけでなくそのクラス ローダーによっても定義されるためです。つまり、2 つの異なるクラス ローダーによってロードされるクラスは同じクラスにはなりません。
これは、カスタム クラス ローダーがその親に委譲しているときに、クラスがより広い範囲で利用できるようにすることを意味します。ほとんどの場合、これはあなたが望むものですが、常にではありません。
何らかの理由でクラスの分離が必要な場合は、カスタム クラス ローダーが逆に実装されている可能性があります。最初に、それ自体でクラスをロードしようとし、クラスが見つからない場合 (または JVM システム クラスまたはスキップしたい他のクラスである場合) にのみ、そのクラスをその親に委譲します。たとえば、Web アプリケーション コンテナーはこのように機能し、コンテキストの再デプロイ (基本的にクラス ローダーを破棄し、すべてを再度ロードする新しいコンテナーを作成します) と Web アプリ間の完全なクラス分離を可能にします。
すでに述べたように、クラスのロードを処理するのは簡単なことではありません。自分が何をしているのかを本当に理解しているか、奇妙なブードゥー教のトラブルに巻き込まれることは間違いありません。
すでに話題から外れているかもしれませんが、クラス ローダーと分離についてもう少し詳しく知りたい場合は、classworldsという古いオープン ソース プロジェクトを確認してください。このプロジェクトは古いものですが、私が提案しているのは、これが小さなプロジェクトであり、簡単に飛び込めるクラス ローディング メカニズムに関する知識に満ちているためです。