5. スタンドアロンの WAR

スタンドアロンのWAR(すなわちEAR に含まれていないWAR)のクラスローダの構成を、下の図に示します。

WAR のクラスローダは、Servlet 用のWebAppクラスローダとJSP用のJSPクラスローダに分かれています。 JSP は実行時に動的にServletに変換されるために、このような構造になっています。 最上位のブートストラップクラスローダから最下位のJSPクラスローダまで、8つのクラスローダが関係しています。

Servlet を読み込むWebAppクラスローダは、/WEB-INF/classesに配置したクラスファイルと/WEB-INF/libに配置したJarライブラリを読み込みます。 一方 JSP を読み込むJSPクラスローダは、/WEB-INFおよび/META-INF以外のディレクトリに配置されているJSPを読み込みます。

5.1. クラスのロード処理の優先順位の制御

WebApp クラスローダは、クラスのロード処理を親クラスローダに委譲するタイミングを、以下の2 つから選択できます。

(1) 親クラスローダ優先。まず親クラスローダにクラスのロードを委譲し、見つからなかった場合にWebAppクラスローダでロード。
(2) WebApp クラスローダ優先。まずWebAppクラスローダでクラスのロードを試みて、見つからなかった場合に親クラスローダにクラスのロードを委譲。

「(1)親クラスローダ優先」は他のクラスローダでも採用されている一般的なクラスの探索方法であり、親のクラスローダでロードするクラスを優先的に利用します。 (2)はWebAppクラスローダ特有の探索方法であり、WebAppクラスローダがロードするクラスを優先的に利用します。 すなわち(2)を採用した場合、Servletは上位のクラスローダがロードするクラスをWEB-INF/classesまたはWEB-INF/libにあるクラスで置換することができます。

ロード処理の優先順位の制御は、WEB-INF/nec-web.xml中の要素<class-loader>の属性delegateで指定します。

<?xml version="1.0" encoding="UTF-8"?>
<nec-web-app>
    <context-root>myapp</context-root>
    <class-loader delegate="true"/>
</nec-web-app>

属性delegate="true"の場合は、「(1)親クラスローダ優先」となり、属性delegate="false"の場合は、「(2) WebAppクラスローダ優先」となります。 要素<class-loader>を省略した場合や、WEB-INF/nec-web.xmlそのものを省略した場合の属性delegateのデフォルト値は、Servletのバージョンによって異なります。 Servlet 2.4以降では属性delegateのデフォルト値は"true"であり、Servlet 2.3以前では"false"です。

以降では、属性delegateの値別に、クラスのロードの具体的な動作を解説します。

5.2. 属性delegate="true"の場合のクラスローダの動作

ここでは、属性delegate="true"の場合のクラスローダの動作について説明します。

まずServletの視点から解説します。クラスローダのロード処理順の概要図を以下に示します。 Servletの視点では、JSPクラスローダはクラスのロード処理に関与しない点に注意してください。

WebAppクラスローダがServlet等のクラスをロードする際、まず親クラスローダであるApplibsクラスローダにクラスのロード処理を委譲します。 Applibsクラスローダを含む上位のクラスローダも、通常どおり先に親クラスローダに処理を委譲します。 そのため優先順位の最も高いクラスローダはブートストラップクラスローダであり、最も優先順位の低いクラスローダはWebAppクラスローダで、優先順位7位になります。

次にJSPの視点から解説します。クラスローダのロード処理順の概要図を以下に示します。

JSPクラスローダはJSPのみをロードする特別なクラスローダです。 JSPクラスローダに対してロード要求があった場合、まずJSPクラスローダ自身でJSPのロードを試みます。 従って、JSPクラスローダが優先順位1位になります。 ロード対象がJSPではない場合、親クラスローダであるWebAppクラスローダにクラスのロード処理を委譲します。 WebAppクラスローダを含む上位のクラスローダも、通常どおり先に親クラスローダにロード処理を委譲します。 そのためブートストラップクラスローダが優先順位2位です。 最も優先順位の低いクラスローダは優先順位8位のWebAppクラスローダです。

5.3. 属性delegate="false"の場合のクラスローダの動作

ここでは、属性delegate="false"の場合のクラスローダの動作について説明します。

まずServletの視点から解説します。クラスローダのロード処理順の概要図を以下に示します。 Servletの視点では、JSPクラスローダは無関係である点に注意してください。

WebAppクラスローダがServlet等のクラスをロードする際、まずWebAppクラスローダ自身でクラスのロードを試みます。 従って、WebAppクラスローダは優先順位1位になります。 WebAppクラスローダでクラスをロードできなかった場合は、親クラスローダであるApplibsクラスローダにクラスのロード処理を委譲します。 Applibsクラスローダを含む上位のクラスローダは、通常どおり先に親クラスローダに処理を委譲します。 そのためブートストラップクラスローダが優先順位2位となり、Applibsクラスローダは優先順位7位になります。

次にJSPの視点から解説します。クラスローダのロード処理順の概要図を以下に示します。

JSPクラスローダはJSPのみをロードする特別なクラスローダです。 JSPクラスローダに対してロード要求があった場合、まずJSPクラスローダ自身でJSPのロードを試みます。 従って、JSPクラスローダが優先順位1位になります。 ロード対象がJSPではない場合、親クラスローダであるWebAppクラスローダにクラスのロード処理を委譲します。 WebAppクラスローダは親クラスローダにロード処理を委譲する前に、自身でクラスのロードを試みます。 従って、WebAppクラスローダは優先順位2位になります。 WebAppクラスローダでクラスをロードできなかった場合は、親クラスローダであるApplibsクラスローダにクラスのロード処理を委譲します。 Applibsクラスローダを含む上位のクラスローダは、通常どおり先に親クラスローダに処理を委譲します。 そのためブートストラップクラスローダが優先順位3位となり、Applibsクラスローダは優先順位8位になります。