Java仮想マシンの配下では、多くのクラスが複雑に(かつ密接に)絡み合い、Javaアプリケーションの動作を支えています。しかし、複数のアプリケーションを利用しているうちに、相互のアプリケーション間で、同名でバージョンだけが異なるクラス(ライブラリ)が必要になったとしたらどうなるでしょう? しかも、そのクラスライブラリには、バージョン間の上位/下位互換性がないとしたら、どうしたらよいでしょうか。
このように、バージョンアップしなければアプリケーションBが動かない、バージョンアップすればアプリケーションAが正常に動かなくなってしまうというケースは、多くのアプリケーションが並存するサーバ上においては、大いにあり得ることです。
そこで、Tomcatのようなコンテナでは、複数のクラスローダに階層関係を持たせることで、個々のクラス(ライブラリ)の独立性を保証しています。クラスローダとは、その名のとおり、ロードしたクラスを管理するためのモジュールで、Java仮想マシンは1つ以上のクラスローダを介して、クラス群の呼び出しを行います。
あるクラスローダがクラスをロードしようとしたときは、必ず親(祖先)のクラスローダによってすでにロードされているクラスが存在しないか確認します。そして、該当するクラスが存在しない場合のみ、自身でロードを行うようになっています。並列関係にあるクラスローダ同士は、まったく独立の関係にあり、たとえ同じクラスがロードされたとしても、一切関与しません。
これによって、複数のアプリケーション間で異なるバージョンのライブラリが並存していたとしても、相互に影響することなく正しい動作を行うことが可能になるのです。コンテナに対して、クラスライブラリを追加導入する場合、このクラスローダの階層関係と有効範囲を知っておくことは、ライブラリの競合による不具合を未然に防ぐために重要な知識であるといえるでしょう。
クラスローダの階層構造は、コンテナによって異なりますが、その差は微少です。ここではTomcat 5.x環境を例に、クラスローダの階層構造を紹介します。
BootStrap └─System └─Common ├─Catalina └─Shared └─WebApp1 : └─WebAppN
BootStrap | すべてのJavaアプリケーションに有効(%JAVA_HOME%\jre\lib\ext) |
---|---|
System | 環境変数CLASSPATHに設定されているクラス(ただし、Tomcat5の標準的な起動スクリプトではCLASSPATHの内容は無視される) |
Common | Tomcatが内部的に使用。全アプリケーションで利用可能(%CATALINA_HOME%\common\lib) |
Catalina | Tomcatが動作時に使用するクラス(%CATALINA_HOME%\server\lib) |
Shared | 全アプリケーションで利用可能なクラス。ただし、Tomcatの実行には使用不可(%CATALINA_HOME%\share\lib) |
WebAppN | 個々のアプリケーション内でのみ利用可能なクラス(%CATALINA_HOME%\webapps\(アプリケーション名)\WEB-INF) |
「%JAVA_HOME%」はJ2SEのインストールフォルダ、「%CATALINA_HOME%」はTomcatのインストールフォルダを、それぞれ表します。
「.class」ファイルをインストールする場合には、個々のフォルダ配下の「classes」フォルダに、「.jar」ファイルをインストールする場合には「lib」フォルダに、それぞれコピーするようにしてください。
注意:ただし、TomcatにおけるWebAppsクラスローダの挙動は、Java2デフォルトの優先順位とは異なっているということに注意してください。WebAppsクラスローダからクラスのロード要求が処理される場合、WebAppsクラスローダは一部の例外(JREの基本クラスなど)を除いて、親のクラスローダに対して確認を行わず、最初に自身のローダを参照します。この機能によって、上位のクラスローダで定義された一部の拡張ライブラリを、WebApps固有のものに置き換えることが可能となります。
Copyright © ITmedia, Inc. All Rights Reserved.