ホームページ > 記事 > ウェブフロントエンド > classloader_html/css_WEB-ITnose によってロードされる親委任モード
ClassLoader を詳しく理解するには、まず ClassLoader が何に使用されるかを知る必要があります。その名前が示すように、プログラムで使用するためにクラス ファイルを JVM にロードするために使用されます。 Java プログラムがクラス定義を動的にロードできること、およびこの動的ロード メカニズムが ClassLoader を通じて実装されていることはわかっているため、ClassLoader の重要性が想像できるでしょう。
これを見て、ある質問を考える友人もいるかもしれません。つまり、ClassLoader はクラスを JVM にロードするために使用されるのですが、ClassLoader はどのようにロードされるのでしょうか? Javaクラスじゃないの?
そうです、ここには Java 言語で書かれたクラスローダーはありませんが、JVM 実装の一部です。このクラスローダーは、JVM の起動時に Java コア API をロードします。ユーザー定義の ClassLoader など、Java プログラムの最も基本的なニーズを満たすために、ここでのいわゆるユーザー定義とは、Java プログラムを通じて実装された ClassLoader を指します。1 つは ExtClassLoader で、この ClassLoader は Java の拡張 API をロードするために使用されます。 / lib/ext 内のクラスのうち、1 つは AppClassLoader です。この ClassLoader は、ユーザーのマシンの CLASSPATH 設定ディレクトリにあるクラスをロードするために使用されます。通常、ClassLoader が指定されていない場合、プログラマがカスタマイズしたクラスが ClassLoader によってロードされます。
プログラムを実行すると、JVM が起動してブートストラップ クラスローダーが実行され、ClassLoader が Java コア API をロードし (この時点で ExtClassLoader と AppClassLoader もロードされます)、次に ExtClassLoader を呼び出して拡張 API をロードし、最後に AppClassLoader がクラスをロードします。 CLASSPATH ディレクトリに定義されており、これはプログラムの最も基本的なロード プロセスです。
上記では、ClassLoader の機能と最も基本的なロード処理について簡単に説明しました。次に、ClassLoader がクラスのロードに使用する親委任モードについて説明します。
すべてのカスタム ClassLoader は抽象クラス ClassLoader を継承する必要があり、各 ClassLoader は親 ClassLoader を持ちます。このメソッドは、現在の ClassLoader の親を返すために使用されます。 . 、この親は継承されたクラスを参照するのではなく、ClassLoader をインスタンス化するときに指定された ClassLoader を参照することに注意してください。親が null の場合、ClassLoader のデフォルトの親はブートストラップ クラスローダーになります。
ClientDefClassLoader をカスタマイズし、このカスタマイズされた ClassLoader を使用して java.lang.String をロードすると仮定すると、このような状況が考えられます。ここでの String はこの ClassLoader によってロードされるでしょうか?実際、java.lang.String クラスは ClientDefClassLoader によってではなく、ブートストラップ クラスローダーによってロードされます。これはなぜでしょうか。実際、これが親委任モードの理由です。カスタム ClassLoader は、クラスをロードする前に、まずその親 ClassLoader にそのクラスのロードを委任し、親 ClassLoader が正常にロードできなかった場合にのみ、クラスローダ自体がロードされます。上に示したように、この例では、java.lang.String は Java コア API に属するクラスであるため、ClientDefClassLoader を使用してロードする場合、前述のように、ClassLoader の親がロードされると、まず ClassLoader がその親 ClassLoader にロードを委託します。 is null このとき、ClassLoader の親はブートストラップ クラスローダーであるため、ClassLoader の最上位はブートストラップ クラスローダーであるため、最終的にブートストラップ クラスローダーに委譲されると、ブートストラップ クラスローダーは String のクラスを返します。
ClassLoader のソース コードの一部を見てみましょう:
protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException{ // 首先检查该name指定的class是否有被加载 Class c = findLoadedClass(name); if (c == null) { try { if (parent != null) { //如果parent不为null,则调用parent的loadClass进行加载 c = parent.loadClass(name, false); }else{ //parent为null,则调用BootstrapClassLoader进行加载 c = findBootstrapClass0(name); } }catch(ClassNotFoundException e) { //如果仍然无法加载成功,则调用自身的findClass进行加载 c = findClass(name); } } if (resolve) { resolveClass(c); } return c; }
上記のコード部分から、クラスをロードする一般的なプロセスが前に示した例と同じであることがわかります。カスタム クラスを実装するときは、findClass メソッドを実装するだけで済みます。
この親委任モデルを使用する理由は何ですか?
1 つ目の理由は、これにより、父親がすでにクラスをロードしている場合、子 ClassLoader がそれを再度ロードする必要がないためです。
2 番目の理由は、セキュリティ要素を考慮することです。この委任モードを使用しない場合、いつでもカスタム String を使用して、Java コア API で定義された型を動的に置き換えることができると考えてください。これはセキュリティ上の大きな問題ですが、起動時に String がロードされるため、ユーザー定義クラスはカスタム ClassLoader をロードできないため、親委任メソッドによってこの状況を回避できます。
ClassLoader のロードメカニズムについては上で簡単に紹介しました。次に、ClassLoader に関連する別のクラス、つまり Class クラスについて説明する必要があります。ClassLoader によってロードされる各クラス ファイルは、最終的にプログラマによって参照されるクラス インスタンスとして分類されます。 Class クラスを共通クラスのテンプレートと見なすことができ、JVM はこのテンプレートに基づいて対応するインスタンスを生成し、最終的にプログラマによって使用されます。
Class クラスには静的メソッド forName があることがわかります。このメソッドは ClassLoader のloadClass メソッドと同じ目的を持っていますが、両方の機能に違いがあります。