9

動機

次のようなクラスローディング階層があるとします。

 Bootstrap
     |
  System
     |
  Custom

CustomClassloader が class のロードに使用されているとしましょうcom.example.SomeClass。クラスローダーがロードできるかどうかをチェックし、Systemクラスローダーがロードできるかどうかを再度チェックBootstrapします。どちらもできないため、クラスローダーcom.example.SomeClassによってロードされCustomます。

com.example.SomeClassに依存するクラスはすべて同じことを行います。私はそのプロセスを理解していると信じています。

質問

そもそもCustomロードしようとする理由がわかりません。com.example.SomeClassJava アプリケーションで現在のクラスローダをどのように選択していますか?

4

2 に答える 2

15

小さなイントロ

ご存じのとおり、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という古いオープン ソース プロジェクトを確認してください。このプロジェクトは古いものですが、私が提案しているのは、これが小さなプロジェクトであり、簡単に飛び込めるクラス ローディング メカニズムに関する知識に満ちているためです。

于 2013-03-06T21:22:27.970 に答える
2

各クラスは、いくつかのメソッドで初めて要求されます。すべてのメソッドは、すでにロードされ、クラスローダーが定義されているクラスの一部です。そのため、新しいクラスが必要な場合は、現在のメソッドのクラスのクラスローダーを介して検索されます。クラスがカスタム クラス ローダーを介してロードされる場合、そのクラスのメソッドによってロードされるすべてのクラスの基本クラスローダーになります。JVM 仕様では、クラスを静的に解決する方法 (起動時にすべてのグラフをロードする) または動的に解決する方法 (初回の要求時) は定義されていません。しかし、静的読み込みには時間がかかりすぎるため使用されず、アプリケーションが既に実行されているときに ClassNotFoundError を受け取ります。クラスとインターフェイスの解決

于 2013-03-06T15:09:20.257 に答える