序文前回の「Java 仮想マシン: オブジェクト作成プロセスとクラス読み込みメカニズム、親委任モデル」の記事では、JVM クラス読み込みメカニズムと親委任モデルについて紹介しました。親委任モデルのクラス読み込みプロセスは、主に次の手順に分かれています。 (1)ClassLoaderを初期化するときに、親が誰であるかを指定する必要があります (2)まずクラスがロードされているかどうかをチェックする。クラスがロードされている場合は直接 (3)ロードされていない場合は、親ローダーのloadClass()メソッドを呼び出してロードする (4)親ローダーが空の場合、デフォルトでブートストラップクラスローダーが使用され、 (5) 親クラスのロードに失敗した場合は、ClassNotFoundExceptionがスローされ、findClass()メソッドが呼び出されてロードされます。 前の記事で述べたように、このメカニズムを破壊したい場合は、クラスローダー(ClassLoader から継承)をカスタマイズし、その中の loadClass() メソッドを書き換えて、親の委譲を実行しないようにすることができます。最も典型的な例は、Tomcat コンテナのクラス ローディング メカニズムです。これは、独自のクラス ローダー WebApp ClassLoader を実装し、親の委任モデルを破壊します。各アプリケーションがデプロイされると、一意のクラス ローダーが作成されます。 1. Tomcat クラスローダー構造図:(1) Common ClassLoader: common.loaderプロパティの下のjarをロードします。通常はCATALINA_HOME/libディレクトリにあり、主にTomcatやアプリケーションの一般的なクラスで使用されます。 (2) Catalina ClassLoader: server.loader プロパティの下にある jar をロードします。デフォルトではパスは設定されておらず、親ローダーである Common ClassLoader を返します。主にサーバー内の表示可能なクラスをロードします。これらのクラスにはアプリケーションからアクセスできません。 (3) 共有クラスローダー: share.loader 属性の下にある jar をロードします。デフォルトではパスは設定されておらず、親ローダーである Common ClassLoader を返します。これは主にアプリケーションの共有クラスをロードするために使用されます。これらのクラスは Tomcat 自体には表示されません。
(4) WebApp ClassLoader: Tomcat は複数の WebApp ClassLoader インスタンスを持つことができます。各アプリケーションには、アプリケーションの /WEB-INF/classes および /WEB-INF/lib の下のクラスをロードするための固有の WebApp ClassLoader があります。 2. Tomcat のクラスロードプロセスの説明:Tomcat がクラスのロードに WebAppClassLoader を使用する場合、具体的なプロセスは次のようになります。 (1) まず、クラスがローカルキャッシュにロードされているかどうかを確認し、Tomcat がクラスをロードしたかどうかを確認します。 (2)Tomcatがこのクラスをロードしていない場合、システムクラスローダーのキャッシュをチェックしてロードされているかどうかを確認します。 (3) そうでない場合は、ExtClassLoader クラスローダーを使用してクラスをロードします。ここでポイントになります。Tomcat の WebAppClassLoader は、最初に AppClassLoader を使用してクラスをロードするのではなく、直接 ExtClassLoader を使用してクラスをロードします。ただし、ExtClassLoader は依然として親の委任に従います。Bootstrap ClassLoader を使用してクラスをロードし、Jre のコア クラスが繰り返しロードされないようにします。 たとえば、Web で Object クラスをロードします。 WebAppClassLoader → ExtClassLoader → Bootstrap ClassLoader、この読み込みチェーンにより、オブジェクトが繰り返し読み込まれないことが保証されます。 (4) 読み込みが成功しなかった場合、WebAppClassLoader は独自の findClass() メソッドを呼び出してクラスを自動的に読み込み、最初に WEB-INF/classes から読み込み、次に WEB-INF/lib から読み込みます。 (5) それでも読み込みが成功しない場合は、WebAppclassLoader は SharedClassLoader に委任し、SharedClassLoader は CommonClassLoader に委任し、CommonClassLoader は AppClassLoader に委任し、最終的に BootstrapClassLoader に委任されて、クラスが独自のディレクトリにレイヤーごとにロードされます。 (6)いずれのファイルも正常に読み込まれなかった場合は例外がスローされます。 3. ソースコード分析:(1) WebAppClassLoaderのloadClass()メソッドのソースコード: WebappClassLoader アプリケーション クラス ローダー loadClass は、親クラス WebappClassLoaderBase にあります。 パブリック Class<?> loadClass(String name, boolean resolve) は ClassNotFoundException をスローします { 同期化 (getClassLoadingLock(名前)) { クラス<?> clazz = null; //1. まず、ローカル キャッシュでクラスがロードされているかどうかを確認します。clazz = findLoadedClass0(name); (clazz != null)の場合{ もし(解決する) クラスを解決します(clazz); 戻りクラッズ; } //2. システム クラス ローダーがロードされているかどうかを確認します clazz = findLoadedClass(name); (clazz != null)の場合{ もし(解決する) クラスを解決します(clazz); 戻りクラッズ; } // 3. ExtClassLoader クラスローダーを使用してクラスをロードします (ExtClassLoader は親の委任に従い、ExtClassLoader は Bootstrap ClassLoader を使用してクラスをロードします) クラスローダー javaseLoader = getJavaseClassLoader(); 試す { clazz = javaseLoader.loadClass(名前); (clazz != null)の場合{ もし(解決する) クラスを解決します(clazz); 戻りクラッズ; } } キャッチ (ClassNotFoundException e) { // 無視する } // 4. ローカルディレクトリでクラスを検索してロードしてみる try { clazz = findClass(名前); (clazz != null)の場合{ もし(解決する) クラスを解決します(clazz); 戻りクラッズ; } } キャッチ (ClassNotFoundException e) { // 無視する } // 5. システムクラスローダー(AppClassLoader)でロードを試みる try { clazz = Class.forName(名前、false、親); (clazz != null)の場合{ もし(解決する) クラスを解決します(clazz); 戻りクラッズ; } } キャッチ (ClassNotFoundException e) { // 無視する } } //6. 上記のプロセスはすべてロードに失敗し、例外をスローします。throw new ClassNotFoundException(name); } (2) WebAppClassLoaderのfindClass()メソッドのソースコード: パブリック Class<?> findClass(String name) は ClassNotFoundException をスローします { // 可能であれば、スーパークラスにこのクラスを見つけるように依頼します // (見つからない場合は ClassNotFoundException をスローします) クラス<?> clazz = null; // まず、自分のWebアプリケーションディレクトリでクラスを検索します clazz = findClassInternal(名前); // 見つからない場合は親クラスで処理します if ((clazz == null) && hasExternalRepositories) { clazz = super.findClass(クラス名); } (clazz == null)の場合{ 新しい ClassNotFoundException(名前) をスローします。 } 戻りクラッズ; } 4. Tomcat が独自のクラスロードメカニズムを実装するのはなぜですか?WebAppClassLoader はクラスをロードするときに、JVM 親委任メカニズムを意図的に破壊し、AppClassLoader をバイパスして、ExtClassLoader を直接使用してクラスをロードします。主な理由は、同じ Web コンテナーにデプロイされた異なる Web アプリケーションで使用されるクラス ライブラリを相互に分離して、異なるプロジェクト間の相互影響を回避するためです。もちろん、他にも次のような理由があります。 (1) Webコンテナ自体のセキュリティがデプロイされたWebアプリケーションの影響を受けないようにするため、Tomcatが使用するクラスライブラリは、デプロイされたアプリケーションのクラスライブラリから独立している必要があります。 (2)いくつかの基本クラスが同時にロードされないようにする。いくつかのクラスライブラリは、サーブレットAPIなど、Tomcatとデプロイされたアプリケーション間で共有できます。 (3)同じWebコンテナにデプロイされたアプリケーション間でクラスライブラリを共有できるようにします。これは主な理由が矛盾しているように聞こえますが、実は非常に合理的です。クラスはクラスローダーによって仮想マシンにロードされた後、メソッド領域の永続世代に保存されます。クラスライブラリを共有できない場合、仮想マシンのメソッド領域が過度に拡張されるリスクに簡単にさらされます。たとえば、多数のアプリケーションを Spring で管理していて、Spring クラス ライブラリを共有できない場合、各アプリケーションの Spring クラス ライブラリが 1 回ずつロードされることになり、リソースが大量に無駄になります。 概要: Tomcat では、WebAppClassLoader ローダーのみが親の委任を破棄しますが、他のクラス ローダーは引き続き親の委任に従います。 これを行う主な理由は、同じ Web コンテナー内の異なる Web アプリケーションで使用されるクラス ライブラリが相互干渉を避けるために互いに独立していることを保証するためです。 参考記事: https://www.jb51.net/article/229561.htm Tomcat のクラスローディングメカニズムのプロセスとソースコード分析に関するこの記事はこれで終わりです。Tomcat のクラスローディングメカニズムに関するより関連性の高いコンテンツについては、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。 以下もご興味があるかもしれません:
|
<<: MySql データベースにおける単一テーブル クエリと複数テーブル結合クエリの効率の比較
>>: CSS クロスブラウザ スタイルのバグのデバッグについて
1. マルチヘッダーテーブルコードコードをコピーコードは次のとおりです。 <!DOCTYPE ...
Linux で MySQL-5.7.19 バージョンをインストールするための最初のチュートリアル。す...
目次コード:補充:要約する要件: 左のツリーと右のテーブル。組織ツリーでノードを選択した後、詳細ペー...
Xhtml には、あまり使用されないが非常に便利なタグが多数あります。半分の労力で 2 倍の結果を達...
序文React 16から、子コンポーネントで発生したエラーを捕捉し、エラーログを記録し、ダウングレー...
この記事では、Element-uiを使用してvue.jsでナビゲーションメニューを実装するための具体...
序文: 「MySQL 入門」シリーズの記事は終了しました。今後も引き続き MySQL に焦点を当て、...
2 つ以上のブロックレベル ボックスの垂直に隣接するエッジが重なり合っています。結果として得られる境...
フロントエンド開発では、スクロールバーを非表示にしながらスクロールをサポートしなければならないという...
目次1. フロントエンド制御1. router.js ファイル内 (router.js にそれぞれ静...
この記事では、参考のために、ミニプログラムでカスタムのマルチレベル単一選択および複数選択機能を実装す...
VirtualBoxのインストールディレクトリを見つけます。ディレクトリ内には容量を拡張するために...
ネットワーク通信の概要オンライン ゲームを開発する場合、必然的にネットワーク通信に対処する必要があり...
目次導入説明書実際の経験まとめ導入MySQL は最も人気のあるオープンソース データベースとして、さ...
データ型と操作データテーブル1.1 MySQL 型: 整数 1.2 MySQL データ型: 浮動小数...