7. EAR のクラスローダ

EARはWAR、EJB、RARを含むことのできる、「アプリケーションのとりまとめ」のような役割を担っています。 そのため、クラスローダの構成も、他のアプリケーションと比べると複雑になっています。 ここでは以下のようなEAR(app.ear)を例に挙げ、解説を行います。

まとめると、app.earは以下のような構成になります。

app.ear
    META-INF/application.xml
    web-app.war (delegate="true"、Class-Path: lib/common.jar)
    other-web-app.war (delegate="false")
    backend-ejb.jar (Class-Path: lib/utilities.jar)
    legacy-ra.rar
    lib/common.jar
    lib/utilities.jar

7.1. クラスローダの構成

app.earを配備した際のクラスローダの構成を以下の図に示します。

EAR のクラスローダは、以下のクラスローダから構成されます。

Applibsクラスローダ

[DOMAIN]/lib/applibs配下の指定したJarをロードするクラスローダです。 Applibsクラスローダの親クラスローダはコネクタクラスローダです。

EAR Libクラスローダ

EAR内のlibディレクトリにあるライブラリをロードするクラスローダです。 このライブラリは、EAR内の全てのモジュールから参照可能です。 ディレクトリは配備記述子(application.xml)の要素<library-directory>で指定できます(デフォルト値はlib)。 EAR Libクラスローダの親クラスローダはApplibsクラスローダです。

EAR内部コネクタクラスローダ

EAR内のRARをロードするクラスローダです。 EAR内部コネクタクラスローダの親クラスローダはEAR Libクラスローダです。

WebOTX V8では、EAR内のRARもメイン内で共通のコネクタクラスローダでロードされており、他のアプリケーションからも利用可能でしたが、WebOTX V9以降ではJava EE 6以降の仕様に準拠するために、EAR内のRARは他のアプリケーションからは利用できないように変更されました。

EJBクラスローダ

EJBをロードするクラスローダです。 EJBクラスローダの親クラスローダはEAR内部コネクタクラスローダです。 EAR内に含まれるEJBの数とは関係なく、必ず1 つだけ存在します。 EJBクラスローダは、EJBだけではなく、マニフェストファイルの属性Class-Pathで指定したライブラリもロードの対象とします。

WebAppクラスローダ/JSPクラスローダ

WARをロードするクラスローダです。EAR内に含まれるWARの数だけ存在します。 WebAppクラスローダの親クラスローダはEJBクラスローダです。 WebAppクラスローダとJSPクラスローダは対になっており、 JSPクラスローダの親クラスローダは、それと対のWebAppクラスローダです。

7.2. EAR 内で共通に利用するJar ライブラリの配置

EARの中には、WARやEJBで共通に利用するライブラリを含めることができます。 Java EE 5以降に準拠したEARでは、EAR内のlibというディレクトリにJarを配置してください。

J2EE 1.4以前に準拠したEARでは、単にEARに含めるだけではロードの対象にはなりません。 そのライブラリを利用するWARやEJBのマニフェストファイルの属性Class-Pathにライブラリのパスを記述する必要があります。 ライブラリのパスは、EARファイルのトップディレクトリからの相対パスでなければいけません。 例えば、web-app.warlib/common.jarを利用するために、web-app.warに次のようなマニフェストファイルを含めます。

Manifest-Version: 1.0
Created-By: 1.5.0_18-b02 (Sun Microsystems Inc.)
Class-Path: lib/common.jar

EAR内で共通に利用するライブラリに着目したapp.earのクラスローダの構成図を以下に示します。 J2EE 1.4以前のEARでは、図にある通りマニフェストファイルにライブラリのパスを記述する必要があります。

EJBでのマニフェストファイルの属性Class-Pathの利用には副作用がある点に注意してください。 EJBのマニフェストファイルの属性Class-Pathに記述したライブラリはEJBクラスローダでロードされるため、その属性を持たないアプリケーションでも利用可能になります。 例えば、other-web-app.warはマニフェストファイル中に属性Class-Pathを持ちませんが、親クラスローダであるEJBクラスローダがlib/utilities.jarをロードしているため、これらのライブラリを利用することができます。

7.3. WARからの視点(delegate="true")

ここではWEB-INF/nec-web.xml<class-loaderdelegate="true"/>を含んでいるweb-app.warについてのクラスローダの動作を説明します。 すなわち、WebAppクラスローダはクラスのロード処理を親クラスローダに優先的に委譲します。 また、もう一つのWARであるother-web-app.warのクラスローダは、クラスのロード処理に関与しない点に注意してください。

まずServlet の視点から解説します。クラスローダのロード処理順の概要図を以下に示します。 Servletの視点では、JSPクラスローダはクラスのロードに関与しません。

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

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

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

7.4. WARからの視点(delegate="false")

ここではWEB-INF/nec-web.xml<class-loaderdelegate="false"/>を含んでいるother-web-app.warについてのクラスローダの動作を説明します。 すなわち、WebAppクラスローダはクラスのロード処理を優先的に自身で行い、クラスが見つからなかった場合に親クラスローダに処理を委譲します。 また、もう一つのWARであるweb-app.warのクラスローダは、クラスのロード処理に関与しない点に注意してください。

まずServletの視点から解説します。クラスローダのロード処理順の概要図を以下に示します。 Servlet の視点では、JSPクラスローダはクラスのロードに関与しません。

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

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

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

7.5. EJBからの視点

ここではEJBの視点からEJBクラスローダの動作を説明します。 EJBクラスローダの動作の概要図を以下に示します。

EJBの視点では、WebAppクラスローダとJSPクラスローダはクラスのロード処理に関与しない点に注意してください。 EJBクラスローダを利用してクラスをロードする場合、まず親クラスローダであるEAR内部コネクタクラスローダにロード処理を委譲します。 EAR内部コネクタクラスローダを含む上位のクラスローダも、通常どおり先に親クラスローダに処理を委譲します。 そのため優先順位の最も高いクラスローダはブートストラップクラスローダであり、最も優先順位の低いクラスローダはEJBクラスローダで、優先順位9位になります。

7.6. RARからの視点

ここではRARの視点からEAR内部コネクタクラスローダの動作を説明します。 EAR内部コネクタクラスローダの動作の概要図を以下に示します。

RARの視点では、EJBクラスローダ、WebApp クラスローダ、JSPクラスローダはクラスのロード処理に関与しない点に注意してください。 EAR内部コネクタクラスローダを利用してクラスをロードする場合、まず親クラスローダであるEAR Libクラスローダにロード処理を委譲します。 EAR Libクラスローダを含む上位のクラスローダも、通常どおり先に親クラスローダに処理を委譲します。 そのため優先順位の最も高いクラスローダはブートストラップクラスローダであり、最も優先順位の低いクラスローダはEAR内部コネクタクラスローダで、優先順位8位になります。