序文前回の「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 クロスブラウザ スタイルのバグのデバッグについて
MySQL 8.0.21のインストールと設定方法を記録してみんなで共有します。 1. ダウンロード1...
目次序文最適化変数の抽出二次包装 el-tag コンポーネント使用要約する序文バックエンドシステムの...
必要ユーザーがフォームに入力して「保存」をクリックすると、PDF ドキュメントを直接ダウンロードでき...
Excel のエクスポートは、docker 環境では常に失敗します。最も直接的な原因は、中国語フォン...
グレースケールリリースとは、白と黒をスムーズに移行できるリリース方法を指します。 ABテストとは、グ...
CentOS6.9+Mysql5.7.18 ソースコードのインストールでは、以下の操作を root ...
HTTPS ウェブサイトの構築コストが下がるにつれて、ほとんどのウェブサイトが HTTPS プロトコ...
ある読者から連絡があり、ダウンロードが終了し、操作がまだ開始されていないのに、なぜ Tomcat の...
この記事は、100 回書かれ、質問された CSS の質問を記念するためのものです。聞く: CSS セ...
目次まず、package.jsonを設定します次にwebpackツールをインストールしますwebpa...
目次1. 画像のバイナリデータを表示する方法2. 絵の種類の見分け方3. 画像の種類を検出する方法3...
目次画像をプルするイメージを実行する(コンテナを生成する)コンテナを起動するコンテナに入るすべてのミ...
序文JavaScript で記述できるアプリケーションは、最終的には JavaScript で記述さ...
Windows のデフォルトのスクロール バー スタイルは見苦しく、プロジェクト内でスクロール バー...
この記事では主に、CSS3 LESS で長いテキストの影を実装する方法を紹介し、皆さんと共有します。...