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

前
 
次
 

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 JavaBeans (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>

フィルタリング・クラス・ローダーの構成のヘルプは、 「クラス・ローダー分析ツール(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://java.sun.com/j2se/1.4/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://download-llnw.oracle.com/javase/tutorial/deployment/jar/manifestindex.htmlを参照してください。

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

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

CATはスタンドアロンWebアプリケーションで、wls-cat.warという単一のWARファイルとして配布され、その機能をWebベースのフロント・エンドを通して公開します。CATは、内部オンデマンド・アプリケーションとして本番モードのみでデプロイされます。デプロイメントは最初のアクセス時に行われます。サーバーが本番モードで稼動している場合、CATは自動的にデプロイされません。本番モードでCATをデプロイできます。その使用には制限がありませんが、他のWebアプリケーションと同様に手動でデプロイする必要があります。CAT WebアプリケーションはWL_HOME/server/lib/wls-cat.warに格納されています。任意のWebLogic Serverバージョン10.3.x以上にデプロイできます。

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

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

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. ドメイン内の管理サーバーとすべての管理対象サーバーを起動します。