ヘッダーをスキップ
Oracle Fusion Middleware Oracle WebLogic Serverアプリケーションの開発
11g リリース1 (10.3.6)
B60990-05
  ドキュメント・ライブラリへ移動
ライブラリ
製品リストへ移動
製品
目次へ移動
目次

前
 
次
 

8 WebLogic Serverアプリケーションのクラスローディングの理解

次の項では、Javaクラスローダーの概要、およびWebLogic Server Java EEアプリケーションのクラスローディングについて説明します。

Javaのクラスローディング

クラスローダーは、Java言語の基本的モジュールです。クラスローダーは、Java仮想マシン(JVM)の構成要素で、クラスをメモリーにロードし、実行時にクラス・ファイルを検索してロードする役割があります。Javaプログラミングを適切に行うためには、クラスローダーとその機能をよく理解する必要があります。この項では、Javaクラスローダーの概要を説明します。

Javaクラスローダーの階層

クラスローダーには、親クラスローダーおよび子クラスローダーからなる階層が含まれます。親クラスローダーと子クラスローダーの関係は、オブジェクトのスーパークラスとサブクラスの関係に似ています。ブート・ストラップ・クラスローダーはJavaクラスローダー階層のルートです。Java仮想マシン(JVM)では、ブート・ストラップ・クラスローダーを作成し、このクラスローダーによって、Java開発キット(JDK)の内部クラスおよびJVMに組み込まれているjava.*パッケージがロードされます。(java.lang.Stringなどがロードされます。)

拡張クラスローダーは、ブート・ストラップ・クラスローダーの子です。拡張クラスローダーは、JDKの拡張ディレクトリにあるすべてのJARファイルをロードします。この機能は、クラスパスにエントリを追加することなくJDKを拡張できるので便利です。ただし、拡張ディレクトリ内にあるものは、すべて完全に独立している必要があり、拡張ディレクトリに含まれているクラスまたはJDKクラスしか参照できません。

システム・クラスパス・クラスローダーは、JDK拡張クラスローダーを拡張します。システム・クラスパス・クラスローダーは、JVMのクラスパスからクラスをロードします。アプリケーション固有のクラスローダー(WebLogic Serverのクラスローダーなど)は、システム・クラスパス・クラスローダーの子です。


注意:

Oracleで「システム・クラスパス・クラスローダー」と呼んでいるクラスローダーは、多くの場合、WebLogic Server以外の文脈上では、「アプリケーション・クラスローダー」と呼ばれています。WebLogic Serverにおけるクラスローダーについて説明する際には、Java EEアプリケーションまたはライブラリ関連のクラスローダー(「アプリケーション・クラスローダー」と呼ぶ)と区別するために「システム」という用語を使用します。


クラスのロード

クラスローダーでは、クラスのロード時に委任モデルを使用します。クラスローダーの実装では、まずキャッシュをチェックして、リクエストされたクラスがすでにロードされていないか確認します。クラスを確認することで、ディスクからクラスを繰返しロードする代わりに、キャッシュ・メモリーのコピーが使用されるのでパフォーマンスが向上します。キャッシュにクラスがなければ、現在のクラスローダーが親にクラスを要求します。親クラスローダーがクラスをロードできない場合のみクラスローダーはクラスのロードを試行します。親と子両方のクラスローダーにクラスがあると、親のクラスがロードされます。この委任モデルに従うのは、複数の同じ形式のコピーがロードされることを防ぐためです。同じクラスのコピーが複数あると、ClassCastExceptionが発生する可能性があります。

クラスローダーは、親クラスローダーにクラスのロードを要求してから、クラスを実際にロードします。Webアプリケーションと関連するWebLogic Serverのクラスローダーは、クラスを親に要求する前にまずローカルをチェックするように構成できます。これにより、Webアプリケーションは独自のサード・パーティ・クラスを使用できるようになります。このサード・パーティ・クラスは、WebLogic Server製品の一部として使用することも可能な場合があります。「prefer-web-inf-classes要素」節では、これについてより詳細に説明しています。

prefer-web-inf-classes要素

weblogic.xml Webアプリケーションのデプロイメント記述子には、<prefer-web-inf-classes要素(<container-descriptor要素のサブ要素)が含まれています。デフォルトでは、この要素はFalseに設定されています。この要素をTrueに設定すると、クラスローダーの委任モデルが無効になり、Webアプリケーションからのクラス定義のほうが、より高度なクラスローダーのクラス定義よりも優先的にロードされるようになります。このため、Webアプリケーションは独自バージョンのサード・パーティ・クラスを使用できるようになります。このクラスは、WebLogic Serverの一部としても使用できる場合があります。「weblogic.xmlデプロイメント記述子の要素」を参照してください。

この機能を使用する場合は、Webアプリケーションのクラス定義から作成されたインスタンスと、サーバーの定義から作成されたインスタンスを混在させないように注意してください。これらのインスタンスが混在していると、ClassCastExceptionが発生します。

例8-1prefer-web-inf-classes要素とその定義およびデフォルト値を示します。

例8-1 prefer-web-inf-classes要素

/** 
* If true, classes located in the WEB-INF directory of a web-app will be
* loaded in preference to classes loaded in the application or system
* classloader. 
* @default false 
*/ 
boolean isPreferWebInfClasses(); 
void setPreferWebInfClasses(boolean b);

実行中プログラムのクラス変更

WebLogic Serverでは、サーバーが稼働中にEJBなどのアプリケーション・モジュールの新しいバージョンをデプロイできます。このプロセスは、ホット・デプロイ、またはホット再デプロイと呼ばれ、クラスのロードと密接な関係があります。

Javaクラスローダーには、クラスをアンデプロイしたり、アンロードしたりする標準メカニズムはありません。また、新しいバージョンのクラスをロードすることもできません。実行中の仮想マシンでクラスを更新するには、変更されるクラスをロードしたクラスローダーを、新しいクラスローダーに置き換える必要があります。クラスローダーが置き換えられると、そのクラスローダー(または、そのクラスローダーの子に当たるクラスローダー)からロードされたすべてのクラスを、再ロードする必要があります。また、これらのクラスのインスタンスはすべて、再インスタンス化する必要があります。

WebLogic Serverでは、各アプリケーションに、システム・クラスローダーの子に当たるクラスローダーからなる階層があります。これらの階層により、アプリケーションまたはアプリケーションの一部が、システムの他の部分に影響を与えることなく個別に再ロード可能です。「WebLogic Serverアプリケーションのクラスローディング」で、このトピックについて説明しています。

クラス・キャッシュの構成

WebLogic Serverは、起動を高速化するためにクラス・キャッシュを有効にできます。キャッシュを有効にすると、サーバーは特定の基準に達するまでロードされるすべてのクラスを記録し、クラス定義を非表示のファイルに保持します。サーバーを再起動すると、キャッシュの有効性が既存のコード・ソースによりチェックされます。そして、サーバーは実行回数に記録されたクラスと同じ一連のクラスをバルク・ロードするためキャッシュ・ファイルを使用します。システム・クラスパスまたはその内容を変更すると、キャッシュは無効になり、サーバー再起動時に再作成されます。

クラス・キャッシュを使用する利点は次のとおりです。

  • サーバーの起動時間が短縮されます。

  • パッケージ・レベルの索引により、すべてのクラスとリソースの検索時間が短縮されます。

キャッシュは、最適化方法を使用して初期キャッシュ記録時間を最小化します。特定のクラスが記録されるまでキャッシュの記録は続行されます。


注意:

startWebLogicスクリプトを使用することで、クラス・キャッシュはサーバーの起動時に開発モードでサポートされます。デフォルトでは、クラス・キャッシュは無効になっており本番モードではサポートされません。開始時間の短縮はベンダーによって異なります。


  1. クラス・キャッシュを有効にするには、startWebLogicスクリプトで環境変数(UNIXの場合CLASS_CACHE=true、Windowsの場合set CLASS_CACHE=true)を設定します。

  2. 次のプロパティを使用して、クラス・キャッシュを構成します。

    • ロギング: クラス・キャッシュの問題をデバッグするには、キャッシュを有効にする起動スクリプトの項に対してJAVA_OPTIONSで次のシステム・プロパティを配置することによりロギングを作動します。

      -Dclass.load.log.level=finest -Dclass.load.log.file=/tmp/class-load-log.txt

      ロギングには、詳細、より詳細、最も詳細の3つのレベルがあります。通常のキャッシュ操作中にロギングを有効にしないでください。ロギングするとサーバーの起動が遅くなります。デバッグするときのみロギングを使用します。

    • 記録制限: クラス・キャッシングの記録制限が特定のクラスに設定されていますが、このクラスはユーザーの環境で別のクラスに構成できます。

      -Dlaunch.complete=<fully qualified class name> たとえば、com.oracle.component.Foo

      このプロパティで使用するクラスは、WebLogic Serverのクラスパスにある必要があります。

例8-2は、クラス・キャッシュが有効でロギングが選択された状態で修正したUNIXおよびWindowsのstartWebLogicスクリプトを示します。

例8-2 startWebLogicスクリプト

On UNIX

# CLASS CACHING
CLASS_CACHE=true
if [ "${CLASS_CACHE}" = "true" ] ; then
        echo "Class caching enabled..."
        JAVA_OPTIONS="${JAVA_OPTIONS} -Dlaunch.main.class=${SERVER_CLASS} 
        -Dlaunch.class.path="${CLASSPATH}" 
        -Dlaunch.complete=weblogic.store.internal.LockManagerImpl 
        -Dclass.load.log.level=finest 
        -Dclass.load.log.file=/tmp/class-load-log.txt 
        -cp ${WL_HOME}/server/lib/pcl2.jar"
        export JAVA_OPTIONS
        SERVER_CLASS="com.oracle.classloader.launch.Launcher"
fi


On Windows

@REM CLASS CACHING
set CLASS_CACHE=true
if "%CLASS_CACHE%"=="true" (
    echo Class caching enabled...
    set JAVA_OPTIONS=%JAVA_OPTIONS% -Dlaunch.main.class=%SERVER_CLASS% 
    -Dlaunch.class.path="%CLASSPATH%" -Dclass.load.log.level=finest 
    -Dclass.load.log.file=C:\class-load-log.txt 
    -Dlaunch.complete=weblogic.store.internal.LockManagerImpl 
    -cp %WL_HOME%\server\lib\pcl2.jar
    set SERVER_CLASS=com.oracle.classloader.launch.Launcher
)

WebLogic Serverアプリケーションのクラスローディング

次の項では、WebLogic Serverアプリケーション・クラスローダーの概要を説明します。

WebLogic Serverアプリケーションのクラスローディングの概要

WebLogic Serverのクラスローディングは、アプリケーションの概念に基づいています。アプリケーションは、通常、アプリケーション・クラスを含むエンタープライズ・アーカイブ(EAR)ファイルにパッケージ化されています。EARファイル内にあるものは、すべて同じアプリケーションの一部と見なされます。次のファイルは、EARの一部になることもでき、またスタンドアロンのアプリケーションとしてロードすることも可能です。

  • Enterprise JavaBean (EJB) JARファイル

  • WebアプリケーションWARファイル

  • リソース・アダプタRARファイル


    注意:

    詳細については、次の各項を参照してください。

    • リソース・アダプタとクラスローディングについては、「リソース・アダプタ・クラス」を参照してください。

    • クラスローディング時の一般的なアプリケーション・ファイルのオーバーライド方法の詳細は、『Oracle WebLogic Serverへのアプリケーションのデプロイ』の汎用ファイル・ロード・オーバーライドに関する項を参照してください。


EJBとWebアプリケーションを別々にデプロイすると、これらは2つのアプリケーションと見なされます。2つのファイルをまとめてEARファイル内にデプロイすれば、1つのアプリケーションとなります。したがって、複数のモジュールが同一アプリケーションの一部と見なされるためには、複数のモジュールをまとめてEARファイルにデプロイします。

すべてのアプリケーションは、独自のクラスローダー階層を受け取ります。この階層の親はシステム・クラスパス・クラスローダーです。したがって、アプリケーションどうしが分離されているため、アプリケーションAからアプリケーションBのクラスローダーおよびクラスを見ることはできません。階層クラスローダーには、兄弟概念またはフレンド概念はありません。アプリケーション・コードは、アプリケーション(またはモジュール)と関連するクラスローダーでロードされたクラス、およびアプリケーション(またはモジュール)クラスローダーの祖先に当たるクラスローダーでロードされたクラスからしか見えません。したがって、WebLogic Serverは同一のJVM内の複数の分離したアプリケーションのホストになります。

アプリケーション・クラスローダーの階層

WebLogic Serverでは、アプリケーションのデプロイ時にクラスローダーの階層が自動的に作成されます。この階層のルート・クラスローダーは、アプリケーション内のすべてのEJB JARファイルをロードします。また、WebアプリケーションWARファイルごとに子クラスローダーが作成されます。

WebアプリケーションによるEJBの呼出しがよくあるため、WebLogic Serverアプリケーション・クラスローダー・アーキテクチャではJavaServer Page (JSP)ファイルおよびサーブレットからその親クラスローダー内のEJBインタフェースを見ることができるようになっています。また、このアーキテクチャではEJB層を再デプロイすることなくWebアプリケーションを再デプロイできます。実際には、EJB層ではなくJSPファイルおよびサーブレットを変更するほうが一般的です。

次の図は、WebLogic Serverアプリケーションのクラスローディング概念を示しています。

図8-1 WebLogic Serverのクラスローディング

図8-1については周囲のテキストで説明しています

アプリケーションにEJBを使用するサーブレットとJSPが含まれる場合:

  • サーブレットとJSPをWARファイルにパッケージ化します。

  • Enterprise JavaBeansをEJB JARファイルにパッケージ化します。

  • このWARファイルとJARファイルをEARファイルにパッケージ化します。

  • パッケージ化したEARファイルをデプロイします。

WARファイルとJARファイルは別々にデプロイできますが、まとめて1つのEARファイルにしてデプロイすることにより、サーブレットとJSPからEJBクラスを検索できるようにクラスローダーが配置されます。WARファイルとJARファイルを別々にデプロイすると、WebLogic Serverではそれらのファイルごとに兄弟クラスローダーを作成します。したがって、そのWARファイルにはEJBホームおよびリモート・インタフェースを含める必要があり、WebLogic Serverでは、EJBクライアントと実装クラスが異なるJVMにある場合と同様に、EJB呼出しにRMIのスタブ・クラスとスケルトン・クラスを使用する必要があります。この概念については、次の「アプリケーション・クラスローディングと、値渡しまたは参照渡し」の項で詳しく説明しています。


注意:

Webアプリケーション・クラスローダーには、JSPクラスを除く、Webアプリケーションのすべてのクラスが含まれます。JSPクラスは、独自のクラスローダーを取得します。これは、Webアプリケーション・クラスローダーの子に当たります。これにより、JSPを個別に再ロードできます。


カスタム・モジュール・クラスローダーの階層

アプリケーション用のカスタム・クラスローダーの階層を作成して、クラスの可視性や再ロードを制御しやすくすることができます。この機能を実現するには、weblogic-application.xmlデプロイメント記述子ファイルでclassloader-structure要素を定義します。

次の図は、WebLogicアプリケーションにおいてクラスローダーがデフォルトではどのように構成されているかを示します。アプリケーション・レベルのクラスローダーは、すべてのEJBクラスがロードされている場所にあります。各Webモジュールについて、そのモジュールのクラス用の子クラスローダーが個別に存在します。

簡素化のため、次の図ではJSPクラスローダーを示していません。

図8-2 標準的なクラスローダーの階層

図8-2については周囲のテキストで説明しています

この階層は、EJB呼出し時にcall-by-referenceセマンティクスを使用できるようになるため、大半のアプリケーションにとって最適です。また、これにより他のモジュールに影響を与えることなくWebモジュールを個別に再ロードできるようになります。さらに、Webモジュールの1つで実行されているコードが、任意のEJBモジュールからのクラスをロードできるようになります。これは、使用しているEJBのインタフェースがWebモジュールに含まれることを防げるため便利です。これらの利点のいくつかは、厳密にはJava EEに準拠していないことに注意してください。

カスタム・モジュール・クラスローダーを作成できると、以下のことが可能になる代替的なクラスローダー構成を宣言するメカニズムが得られます。

  • 個々のEJBモジュールを単独で再ロード

  • モジュールのグループを、一緒に再ロード

  • 特定のWebモジュールとEJBモジュールの親子関係を逆転

  • EJBモジュール間でネームスペースを分離

クラスローダーの階層の宣言

Weblogic固有のアプリケーション・デプロイメント記述子weblogic-application.xml内でクラスローダーの階層を宣言できます。

この宣言のDTDは次のとおりです。

例8-3 クラスローダーの階層の宣言

<!ELEMENT classloader-structure (module-ref*, classloader-structure*)>
<!ELEMENT module-ref (module-uri)>
<!ELEMENT module-uri (#PCDATA)>

weblogic-application.xmlの最上位要素には、オプションclassloader-structure要素が含まれます。この要素を指定しない場合は、標準のクラスローダーが使用されます。また、定義の中に特定のモジュールを含めなかった場合、標準的な階層と同様にクラスローダーが割り当てられます。つまり、EJBモジュールはアプリケーションのルート・クラスローダーと関連付けられ、Webアプリケーション・モジュールは独自のクラスローダーを持ちます。

classloader-structure要素により、classloader-structureスタンザのネスティングが可能になって、クラスローダーの任意階層を記述できるようになります。現在は、3レベルに制限されています。最も外側のエントリは、アプリケーション・クラスローダーを示します。リストされていないモジュールについては、標準的な階層であると仮定されます。


注意:

JSPクラスローダーは、この定義スキームには含まれません。JSPは常に、所属するWebモジュールと関連のクラスローダーの子クラスローダーにロードされます。


DTD要素の詳細は、付録A「エンタープライズ・アプリケーションのデプロイメント記述子の要素」を参照してください。

以下は、クラスローダーの宣言例です(weblogic-application.xmlclassloader-structure要素で定義)。

例8-4 クラスローダーの宣言例

<classloader-structure> 
   <module-ref> 
      <module-uri>ejb1.jar</module-uri> 
   </module-ref>
   <module-ref> 
      <module-uri>web3.war</module-uri> 
   </module-ref>

   <classloader-structure> 
      <module-ref> 
         <module-uri>web1.war</module-uri> 
      </module-ref> 
   </classloader-structure>

   <classloader-structure> 
      <module-ref> 
         <module-uri>ejb3.jar</module-uri> 
      </module-ref> 
      <module-ref> 
         <module-uri>web2.war</module-uri> 
      </module-ref>

      <classloader-structure> 
         <module-ref> 
            <module-uri>web4.war</module-uri> 
         </module-ref> 
      </classloader-structure> 
      <classloader-structure> 
         <module-ref> 
            <module-uri>ejb2.jar</module-uri> 
         </module-ref> 
      </classloader-structure>
   </classloader-structure>
</classloader-structure>

ネスティングの構成は、クラスローダーの階層を示します。上記のスタンザにより、次の図に示す階層がもたらされます。

図8-3 クラスローダーの階層の例

図8-3については周囲のテキストで説明しています

ユーザー定義のクラスローダーの制約

ユーザー定義のクラスローダーの制約により、再ロードできるものが制御しやすくなり、モジュール間でのクラスの可視性が提供されます。この特徴は主に開発者のためのものです。繰返し開発が行われる場合には有用ですが、本番環境で使用する目的の場合には再ロード機能の使用はお薦めしません。更新時に無効な要素が含まれると、実行中のアプリケーションが破損するおそれがあるためです。ネームスペースの分離とクラス可視性のためのカスタム・クラスローダーの配置は、本番環境で使用する場合においても容認できるものです。ただし、Java EE仕様にはアプリケーションがいかなるクラスローダー構成にも依存してはならないと書いてあることに、プログラマは注意する必要があります。

一部のクラスローダー階層は、アプリケーション内のモジュールが2つの別個のアプリケーションのモジュールのように動作する原因となる可能性があります。たとえば、EJBを独自のクラスローダーに配置して個別に再ロードできるようにすると、Oracleが標準的なクラスローダー階層に提供しているcall-by-referenceによる最適化ではなく、call-by-valueセマンティクスを受け取ります。また、カスタム階層を使用すると、参照が古いものになる可能性があります。したがって、EJBモジュールを再ロードする場合は、呼出し側モジュールも再ロードしてください。

ユーザー定義によるモジュール・クラスローダー階層の作成には、いくつかの制約があります。これらについてはこれ次の項で説明します。

サーブレット再ロードの無効化

カスタム・クラスローダー階層を使用する場合は、その特定のアプリケーションにおけるWebアプリケーションについては、サーブレットの再ロードは無効化されます。

ネスティングの深さ

ネスティングは、3つのレベルまでに制限されています(アプリケーション・クラスローダーを含む)。ネスティングが深くなると、デプロイメント例外が発生します。

モジュール・タイプ

カスタム・クラスローダー階層は、現在はWebおよびEJBモジュールに限定されています。

重複エントリ

エントリが重複すると、デプロイメント例外が発生します。

インタフェース

標準のWebLogic Serverクラスローダー階層により、EJBインタフェースがアプリケーション内のすべてのモジュールで利用可能になります。したがって、それ自体のモジュールにインタフェースが含まれていなくても、他のモジュールがEJBを呼び出せます。これが可能なのは、EJBは常にルート・クラスローダーにロードされ、その他のモジュールはすべてそのクラスローダーを共有するか、そのクラスローダーの子に相当するクラスローダーを持つことになるためです。

カスタム・クラスローダー機能があれば、呼び出される側のクラスが呼出し側から見えないようにクラスローダー階層を構成することが可能です。この場合、呼出し側モジュールにインタフェース・クラスを含める必要があります。これは、別個のアプリケーションのモジュールに対して呼出しを行っている場合の要件と同じです。

call-by-valueセマンティクス

WebLogic Serverに設けられた標準クラスローダー階層により、アプリケーション内のモジュール間での呼出しでcall-by-referenceセマンティクスを使用することが可能となります。これは、呼出し側が常に同じクラスローダーまたは呼び出される側の子クラスローダーを使用しているためです。この機能により、2つのモジュールがクラスローダー・ツリーにおける別々のブランチに存在するように、クラスローダー階層を構成することが可能になります。この場合、call-by-valueセマンティクスが使用されます。

処理中の作業

再ロードに必要となるクラスローダーの切替えは、複数モジュールに渡って原子性を保たないことに留意してください。実際、アプリケーションの更新は、一般に原子性を保ちません。この理由により、タイミングによっては、異なった処理中の操作(変更が行われているときに発生している操作)が、異なったバージョンのクラスにアクセスすることになる可能性があります。

開発用途のみ

development-use-only機能は、開発に使用することが意図されています。更新は原子性を保たないので、この機能は本番に使用するには適していません。

実装クラスのための個々のEJBクラスローダー

WebLogic Serverを使うと、他のモジュールを同時に再ロードして、EJBモジュール全体を再デプロイする必要なしに、個々のEJBモジュールを再ロードできます。この機能は、現在JSPがWebLogic Serverサーブレットのコンテナに再ロードされている方法に類似しています。

EJBクラスはインタフェースを通じて呼び出されるため、個々のEJB実装クラスをそれ自身のクラスローダーにロードすることが可能です。このようにして、これらのクラスはEJBモジュール全体を再デプロイすることなく個別に再ロードできます。次の図は、単一のEJBモジュールのクラスローダー階層の一例です。2つのEJB (FooおよびBar)が含まれています。これは、前の項で説明した一般的なアプリケーション階層におけるサブツリーと考えられます。

図8-4 単一のEJBモジュールのクラスローダー階層の例

図8-4については周囲のテキストで説明しています

展開されたアプリケーションのルートを基準とした相対的な場所にあるファイルの部分的な更新を実行するには、次のコマンド・ラインを使用します。

例8-5 部分的ファイル更新の実行

java weblogic.Deployer -adminurl url -user user -password password 
-name myapp -redeploy myejb/foo.class

-redeployコマンドの後で、更新したい展開アプリケーションのルートを基準として相対的にファイルのリストを指定します。これは、(上記のような)特定の要素へのパスであっても、モジュール(または任意の要素およびモジュールのセット)へのパスであってもかまいません。例:

例8-6 更新のための相対ファイル・リストの指定

java weblogic.Deployer -adminurl url -user user -password password 
-name myapp -redeploy mywar myejb/foo.class anotherejb

更新するファイル群を指定されると、システムは再デプロイの最小要件を計算しようとします。EJB implクラスのみを再デプロイすると、そのクラスのみが再デプロイされることになります。EJB全体(上の例ではanotherejb)を指定するか、またはEJBホーム・インタフェースを変更して更新する場合、EJBモジュール全体の再デプロイが必要です。

クラスローダーの階層によっては、この再デプロイメントで他のモジュールが再デプロイされることになる可能性があります。具体的には、他のモジュールがEJBクラスローダーを共有する場合や、(WebLogic Serverの標準クラスローダー・モジュールのように) EJBクラスローダーの子クラスローダーにロードされる場合は、これらのモジュールも再ロードされます。

アプリケーション・クラスローディングと、値渡しまたは参照渡し

最近のプログラミング言語では、パラメータを渡すときのモデルとして、値渡しと参照渡しがよく使用されます。値渡しの場合、パラメータおよび戻り値はメソッドの呼出しごとにコピーされます。参照渡しの場合は、実際のオブジェクトを示すポインタ(または参照)がメソッドに渡されます。参照渡しでは、オブジェクトをコピーしなくてもよく、渡されたパラメータの状態を変更するメソッドも使用できるため、パフォーマンスが向上します。

WebLogic Serverでは、サーバー内のリモート・メソッド・インタフェース(RMI)呼出しのパフォーマンス向上のための最適化機能もあります。値渡しおよびRMIサブシステムのマーシャリングやアンマーシャリング機能を使用するのではなく、参照渡しを使用することによって、サーバーがダイレクトJavaメソッド呼出しを行います。この方式により、パフォーマンスが大幅に改善され、EJB 2.0ローカル・インタフェースにもこの方式が採用されています。

RMI呼出しの最適化および参照呼出しが使用されるのは、呼出し側と呼び出された側が共に同じアプリケーションにある場合に限られます。通常、クラスローダーが関係します。アプリケーションにはそれぞれ独自のクラスローダー階層があるため、どのアプリケーション・クラスも両方のクラスローダーに定義があり、複数のアプリケーション間で割当てを行おうとするとClassCastExceptionエラーを受け取ります。この問題を回避するため、WebLogic Serverでは複数のアプリケーション間での呼出しには、同じJVM内であっても値呼出しを使用しています。


注意:

複数アプリケーション間の呼出しは、同一アプリケーション内の呼出しに比べて遅くなります。したがって、モジュールは1つのEARファイルにまとめてデプロイし、高速のRMI呼出しおよびEJB 2.0ローカル・インタフェースを使用できるようにしてください。


フィルタリング・クラスローダーの使用

WebLogic Serverでは、システム・クラスパスにあるJARファイルはWebLogic Serverのシステム・クラスローダーによってロードされます。サーバー・インスタンスの内部で実行されるすべてのアプリケーションは、システム・クラスローダーの子であるアプリケーション・クラスローダー内にロードされます。このシステム・クラスローダーの実装では、アプリケーションは、システム・クラスローダー内にすでに存在する異なるバージョンのサードパーティ製JARを使用できません。すべての子クラスローダーは親(システム・クラスローダー)に対して特定のクラスを要求します。親から見えるクラスをロードすることはできません。

たとえば、com.foo.Bazというクラスが$CLASSPATHとアプリケーションEARの両方に存在する場合は、$CLASSPATHにあるクラスがロードされて、EARのクラスはロードされません。weblogic.jar$CLASSPATHにあるため、アプリケーションはWebLogic Serverクラスをオーバーライドすることはできません。

次の項では、フィルタリング・クラスローダーの定義と使用方法について説明します。

フィルタリング・クラスローダーとは

FilteringClassLoaderは、デプロイメント記述子を構成することで、特定のパッケージがシステム・クラスローダーによってロードされるのではなく、常にアプリケーションからロードされるように明示的に指定するメカニズムです。これによって、XercesやAntなどの代替バージョンのアプリケーションを使用できるようになります。FilteringClassLoaderを使用することにより、サード・パーティJARをバンドルしてアプリケーションに使用できますが、javaxパッケージまたはweblogicパッケージ内のクラスのようなAPIクラスに対してフィルタ処理を行うことはお薦めしません。

FilteringClassLoaderはアプリケーション・クラスローダーとシステム・クラスローダーの間に位置します。システム・クラスローダーの子であり、アプリケーション・クラスローダーの親となります。FilteringClassLoaderloadClass(String className)メソッドをインターセプトして、weblogic-application.xmlファイルに指定されているパッケージのリストとclassNameを比較します。パッケージとclassNameが一致する場合、FilteringClassLoaderClassNotFoundExceptionをスローします。この例外は、このクラスをアプリケーションからロードするようにアプリケーション・クラスローダーに通知します。

FilteringClassLoaderの構成

FilteringClassLoaderを構成して、特定のパッケージがアプリケーションからロードされることを指定するには、アプリケーションからロードされるパッケージのリストを記述しているweblogic-application.xmlに、prefer-application-packages記述子要素を追加します。次の例は、org.apache.log4j.*パッケージとantlr.*パッケージがシステム・クラスローダーではなくアプリケーションからロードされることを示します。

<prefer-application-packages>
  <package-name>org.apache.log4j.*</package-name>
  <package-name>antlr.*</package-name>
</prefer-application-packages>

prefer-application-packages記述子要素は、weblogic.xmlでも定義できます。詳細は、「prefer-application-packages」を参照してください。

フィルタリング・クラスローダーの構成のヘルプは、 「クラスローダー分析ツール(CAT)の使用」に関する項を参照してください。

リソースのロード順序

リソースのロード順序は、java.lang.ClassLoadergetResource()およびgetResources()メソッドがリソースを戻す順序です。フィルタが有効になっている場合、この順序はフィルタ処理が無効な場合とは若干異なります。フィルタが有効になっているということは、FilteringClassLoaderに1つまたは複数のパッケージ・パターンがあることを意味しています。フィルタがない場合(デフォルト)、リソースはクラスローダー・ツリーの上から下へという順序で収集されます。たとえば、Web (1)がリソースをリクエストすると、リソースはシステム(3)、アプリケーション(2)、Web(1)の順序でグループ化されます。図8-7を参照してください。

図8-7 システム・クラスローダーの使用

System (3)
   |
  App (2) 
   |
  Web (1)

具体的にいうと、すべてのクラスローダーに存在するリソース/META-INF/foo.xmlの場合は、以下のURLのリストが返されます。

META-INF/foo.xml - from the System ClassLoader (3)
META-INF/foo.xml - from the App ClassLoader (2)
META-INF/foo.xml - from the Web ClassLoader (1)

フィルタリングが有効になっている場合は、システム・クラスローダーのリソースよりも前に、FilteringClassLoaderの子(アプリケーション・クラスローダー)から呼出し側のクラスローダーまでのリソースが戻されます。図8-8では、(D)、(B)、および(A)のすべてのクラスローダーに同じリソースが存在する場合、Webクラスローダーがリソースをリクエストすると、リソースは次のような順序で取得されます。

META-INF/foo.xml - from the App ClassLoader (B)
META-INF/foo.xml - from the Web ClassLoader (A)
META-INF/foo.xml - from the System ClassLoader (D)

注意:

FilteringClassLoaderの下で、リソースはデフォルトのJava EE委任モデルに従って返されます。FilteringClassLoaderの親に存在するリソースのみが、返される列挙の最後に追加されます。


図8-8 フィルタリング・クラスローダー実装の使用

System (D)
  |
  FilteringClassLoader (filterList := x.y.*) (C)
   |
  App (B)
   |
  Web (A)

アプリケーション・クラスローダーが同じリソースをリクエストした場合は、次のような順序になります。

META-INF/foo.xml - from the App ClassLoader (B)
META-INF/foo.xml - from the System ClassLoader (D)

getResource()の場合は、最初の記述子のみが返されて、getResourceAsStream()は最初のリソースのinputStreamを返します。

モジュールおよびアプリケーション間のクラス参照の解決

アプリケーションでは、エンタープライズBean、サーブレットとJavaServer Pages、ユーティリティ・クラス、およびサード・パーティ製パッケージなど、様々なJavaクラスを使用します。WebLogic Serverでは、個別のクラスローダーにアプリケーションをデプロイして、独立を維持し、動的な再デプロイメントとアンデプロイメントを容易にします。このため、各モジュールが各クラスに個別にアクセスできるようにアプリケーションのクラスをパッケージ化する必要があります。場合によっては、一連のクラスを複数のアプリケーションまたはモジュールに格納する必要があります。この項では、アプリケーションを正常にステージングするために、WebLogic Serverで複数のクラスローダーを使用する方法について説明します。

クラスローディング問題の分析および解決の詳細は、「クラスローダー分析ツール(CAT)の使用」に関する項を参照してください。

リソース・アダプタ・クラス

各リソース・アダプタは、固有のクラスローダーを使用してクラスをロードするようになりました(Webアプリケーションの場合に類似)。その結果、アプリケーション・アーカイブ(EARファイル)でリソース・アダプタと一緒にパッケージ化されているWebアプリケーションやEJBなどのモジュールは、リソース・アダプタのクラスへの可視性を持ちません。そのような可視性が必要な場合は、リソース・アダプタのクラスをAPP-INF/classesに置く必要があります。また、これらのクラスを(JARユーティリティを使用して)アーカイブし、それらをアプリケーション・アーカイブのAPP-INF/libに置くこともできます。

リソース・アダプタ固有のクラスがWebLogic Serverのシステム・クラスパスにないことを確認してください。リソース・アダプタ固有のクラスをWebモジュール(EJB、Webアプリケーションなど)と共に使用する必要がある場合、それらのクラスを該当するモジュールのアーカイブ・ファイル(EJBに使用するJARファイルまたはWebアプリケーションに使用するWARファイルなど)にまとめます。

共有ユーティリティ・クラスのパッケージ化

WebLogic Serverは、EARファイル内で共有ユーティリティ・クラスを格納できる場所を提供します。ユーティリティJARファイルはAPP-INF/libディレクトリに、個々のクラスはAPP-INF/classesディレクトリに置きます。(Jarファイルを/classesディレクトリに置いたり、クラスを/libディレクトリに置いたりしないでください)。これらのクラスは、アプリケーションのルート・クラスローダーにロードされます。

この機能により、(どちらに置くかは標準のWebLogic Serverクラスローダーの階層によって変わりますが)システム・クラスパス内にユーティリティ・クラスを置く必要や、EJB JARファイル内にクラスを置く必要はなくなります。この機能を使用する場合は、次の節で説明するマニフェストClass-Pathを使う場合とは少し異なることに注意してください。この機能を使うと、クラス定義はアプリケーション全体で共有されます。マニフェストClass-Pathでは、参照しているモジュールのクラスパスが単純に拡張されます。つまり、クラスのコピーが別々に各モジュールについて存在するということです。

マニフェスト・クラスパス

Java EE仕様では、クラスの補助的なJARファイルを必要とすることをモジュールで指定する手段としてマニフェストClass-Pathエントリが用意されています。このマニフェストClass-Pathエントリを使用するのは、EJB JARファイルまたはWARファイルの一部として追加の補助的なJARファイルがある場合に限られます。その場合、JARファイルまたはWARファイルの作成時に、必要なJARファイルを参照するClass-Path要素と共にマニフェスト・ファイルを含める必要があります。

utility.jarファイルを参照する簡単なマニフェスト・ファイルを以下に示します。

Manifest-Version: 1.0 [CRLF]
Class-Path: utility.jar [CRLF]

このマニフェスト・ファイルの先頭行には、常にManifest-Version属性を指定する必要があり、次に改行(CR | LF |CRLF)、そしてClass-Path属性が続きます。マニフェスト・フォーマットの詳細は、http://docs.oracle.com/javase/1.4.2/docs/guide/jar/jar.html#JARを参照してください。

マニフェストClass-Pathエントリは、エントリが定義されている現在のアーカイブを基準として他のアーカイブを参照します。この構造により、複数のWARファイルおよびEJB JARファイルで、共通のライブラリJARを共有できます。たとえば、WARファイルにy.jarというマニフェスト・エントリが含まれる場合、このエントリは、以下のように、(WARファイル内ではなく)WARファイルの次に指定する必要があります。

/<directory>/x.war
/<directory>/y.jars

マニフェスト・ファイル自体は、META-INF/MANIFEST.MFのアーカイブに配置します。

詳細は、http://docs.oracle.com/javase/tutorial/deployment/jar/manifestindex.htmlを参照してください。

クラスローダー分析ツール(CAT)の使用

CATとはWebベースのクラス分析ツールで、クラスローダー構成のフィルタリングを簡素化し、競合状態の検出、アプリケーションのクラスパスやクラス競合のデバッグといったクラスローディング問題の分析をサポートし、問題解決に役立つソリューションを提案します。

CATはスタンドアロンWebアプリケーションです。wls-cat.warという1つのWARファイルとして配布され、その機能はWebベース・フロントエンドを使用して公開されます。CATは、開発モードでのみ内部オンデマンド・アプリケーションとしてデプロイされます。デプロイメントは初回のアクセス時に実行されます。サーバーが本番モードで稼働中の場合、自動的にデプロイされません。CAT Webアプリケーションは、WL_HOME/server/lib/wls-cat.warに格納されます。WebLogic Server(バージョン10.3.x以降)をそれにデプロイできます。


注意:

CATは、ログイン資格証明を暗号化せずに送信できるBasic認証を使用します。したがって、CATを使用して実行した後は、これをアンデプロイまたは停止し、本番環境ではCATをデプロイしないことをお薦めします。

CATが本番環境にデプロイされている場合は、ただちにCATにアクセスできないようにする必要があります。アクセスの停止の詳細は、次のトピックのいずれかを参照してください。

  • 『Oracle WebLogic Serverへのアプリケーションのデプロイ』の停止に関する項

  • Oracle WebLogic Server管理コンソール・ヘルプのデプロイ済Webアプリケーションの停止に関する項

Basic認証については次の点に注意してください。

  • ユーザー名とパスワードはBase64でエンコードされますが、Base64エンコーディングはセキュリティを目的として提供されているのではなく、ユーザー名またはパスワードに含まれる可能性があるHTTP非互換文字をHTTP互換にエンコードするためのものです。

  • Basic認証により、システムが、リプレイ攻撃および介在者攻撃に対して脆弱になる可能性があります。

  • 既存のブラウザでは、認証情報が無期限に保持されます。HTTPでは、サーバーがクライアントにこれらのキャッシュされた資格証明を破棄するように指示する方法が提供されていません。つまり、ブラウザを閉じる以外にサーバーがユーザーをログアウトさせる効果的な方法はありません。


CATの使用を開始するには:

CATには、現在実行中のアプリケーションとモジュールをすべて表示する単一のWeb GUIが実装されています。左側のナビゲーション・ペインでは、分析するアプリケーションやモジュールを選択できます。右側のペインには選択したアイテムの簡単な説明が表示されます。右側のペインを使用して、選択したアプリケーションやモジュールに関するアクションと分析を実行できます。CATを使用すると次を実行できます。

CATは、システム・クラスパス・クラスローダーやWebLogic Serverのメイン・アプリケーションのクラスローダーによってロードされ、フィルタリング、アプリケーション、およびモジュールのクラスローダーとして定義されたクラスを分析します。クラス、パッケージ、またはJARのレベルで分析を実行できます。選択する各アクションの結果は、基本ビューまたは詳細ビューで表示されます。

CATを使用して実行できるタスクの例を紹介します。

Java EEライブラリを使用したアプリケーションとモジュールの共有

Java EEライブラリ機能により、複数のエンタープライズ・アプリケーション間で、種類が異なる1つまたは複数のJava EEモジュールを簡単に共有できます。Java EEライブラリは、デプロイメントに際してJava EEアプリケーション・コンテナに登録される1つまたは複数のモジュールです。詳細は、第9章「共有Java EEライブラリおよびオプション・パッケージの作成」を参照してください。

ドメイン/libディレクトリへのJARの追加

WebLogic Serverでは、ドメイン・ディレクトリ内にlibサブディレクトリがあります。ドメイン内のWebLogic Serverインスタンスで実行しているすべてのJava EEアプリケーションで(別のシステム・レベル・クラスローダー内)JARファイル・クラスが使用可能になるように、このサブディレクトリを使用して1つまたは複数のJARファイルを追加できます。ドメイン/libディレクトリ内のJARは、システム・クラスパスに追加されません。作成されるクラスローダーは、システム・クラスローダーの子です。ドメイン/libディレクトリのJAR内のすべてのクラスがEARファイルなどのJava EEアプリケーションからのみ参照可能です。システム・クラスパスのクラスはドメイン/libディレクトリ内のクラスにアクセスできません。

libサブディレクトリは、サーバーにデプロイされているすべてまたは大部分のアプリケーションで必要とされ、ほとんど変更されないJARファイルを格納するためのディレクトリです。たとえば、libディレクトリを使用して、ドメイン内のすべてのJava EEデプロイメントで必要とされるサード・パーティ・ユーティリティ・クラスを格納できます。ドメイン/libクラスローダーはすべてのJava EEアプリケーションの親であるため、サード・パーティ・ユーティリティ・クラスが使用可能になります。

libディレクトリは、ドメインにデプロイされている1つまたは2つのアプリケーションでJARを共有したり、定期的に更新する必要があるJARを共有したりする際の一般的な方法としては推奨できません。libディレクトリ内のJARを更新する場合は、アプリケーションが変更を認識できるように、ドメイン内の全サーバーを再起動する必要があります。複数のアプリケーション間でJARファイルまたはJava EEモジュールを共有する必要がある場合は、第9章「共有Java EEライブラリおよびオプション・パッケージの作成」で説明されているJava EEライブラリ機能を使用します。

libディレクトリでJARを共有するには:

  1. ドメイン内のすべてのサーバーを停止します。

  2. 共有するJARファイルをドメイン・ディレクトリのlibサブディレクトリにコピーします。例:

    mkdir c:\bea\wlserver_10.3\samples\domains\wl_server\lib
    cp c:\3rdpartyjars\utility.jar
      c:\bea\wlserver_10.3\samples\domains\wl_server\lib
    

    注意:

    WebLogic Serverは、起動時にlibディレクトリに読込みアクセスできるようにする必要があります。

    管理サーバーは、libディレクトリ内のファイルを、リモート・マシン上の管理ターゲット・サーバーに自動的にコピーしません。管理ターゲット・サーバーが、管理サーバーと同じ物理ドメイン・ディレクトリを共有していない場合、管理ターゲット・サーバー・マシン上のdomain_name/libディレクトリに手動でJARファイルをコピーする必要があります。


  3. ドメイン内の管理サーバーとすべての管理対象サーバーを起動します。