Oracle® Fusion Middleware Oracle WebLogic Serverアプリケーションの開発 11g リリース1(10.3.4) B60990-02 |
|
前 |
次 |
次の項では、Javaクラス・ローダーの概要、およびWebLogic Server Java EEアプリケーションのクラス・ローディングについて説明します。
クラス・ローダーは、Java言語の基本的モジュールです。クラス・ローダーは、Java仮想マシン(JVM)の構成要素で、クラスをメモリーにロードし、実行時にクラス・ファイルを検索してロードする役割があります。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要素」の項では、これについてより詳細に説明しています。
weblogic.xml
Webアプリケーションのデプロイメント記述子には、<prefer-web-inf-classes>
要素(<container-descriptor>
要素のサブ要素)が含まれています。デフォルトでは、この要素はFalse
に設定されています。この要素をTrue
に設定すると、クラス・ローダーの委託モデルが無効になり、Webアプリケーションからのクラス定義のほうが、より高度なクラス・ローダーのクラス定義よりも優先的にロードされるようになります。このため、Webアプリケーションは独自バージョンのサード・パーティ・クラスを使用できるようになります。このクラスは、WebLogic Serverの一部としても使用できる場合があります。「weblogic.xmlデプロイメント記述子の要素」を参照してください。
この機能を使用する場合は、Webアプリケーションのクラス定義から作成されたインスタンスと、サーバーの定義から作成されたインスタンスを混在させないように注意してください。これらのインスタンスが混在していると、ClassCastException
が発生します。
例8-1はprefer-web-inf-classes
要素とその定義およびデフォルト値を示します。
WebLogic Serverでは、サーバーが稼働中にEJBなどのアプリケーション・モジュールの新しいバージョンをデプロイできます。このプロセスは、ホット・デプロイ、またはホット再デプロイと呼ばれ、クラスのロードと密接な関係があります。
Javaクラス・ローダーには、クラスをアンデプロイしたり、アンロードしたりする標準メカニズムはありません。また、新しいバージョンのクラスをロードすることもできません。実行中の仮想マシンでクラスを更新するには、変更されるクラスをロードしたクラス・ローダーを、新しいクラス・ローダーに置き換える必要があります。クラス・ローダーが置き換えられると、そのクラス・ローダー(または、そのクラス・ローダーの子に当たるクラス・ローダー)からロードされたすべてのクラスを、再ロードする必要があります。また、これらのクラスのインスタンスはすべて、再インスタンス化する必要があります。
WebLogic Serverでは、各アプリケーションに、システム・クラス・ローダーの子に当たるクラス・ローダーからなる階層があります。これらの階層により、アプリケーションまたはアプリケーションの一部が、システムの他の部分に影響を与えることなく個別に再ロード可能です。「WebLogic Serverアプリケーションのクラス・ローディング」で、このトピックについて説明しています。
WebLogic Serverは、起動を高速化するためにクラス・キャッシュを有効にできます。キャッシュを有効にすると、サーバーは特定の基準に達するまでロードされるすべてのクラスを記録し、クラス定義を非表示のファイルに保持します。サーバーを再起動すると、キャッシュの有効性が既存のコード・ソースによりチェックされます。そして、サーバーは実行回数に記録されたクラスと同じ一連のクラスをバルク・ロードするためキャッシュ・ファイルを使用します。システム・クラスパスまたはその内容を変更すると、キャッシュは無効になり、サーバー再起動時に再作成されます。
クラス・キャッシュを使用する利点は次のとおりです。
サーバーの起動時間が短縮されます。
パッケージ・レベルの索引により、すべてのクラスとリソースの検索時間が短縮されます。
キャッシュは、最適化方法を使用して初期キャッシュ記録時間を最小化します。特定のクラスが記録されるまでキャッシュの記録は続行されます。
注意: startWebLogic スクリプトを使用することで、クラス・キャッシュはサーバーの起動時に開発モードでサポートされます。デフォルトでは、クラス・キャッシュは無効になっており本番モードではサポートされません。開始時間の短縮はベンダーによって異なります。 |
クラス・キャッシュを有効にするには、startWebLogic
スクリプトで環境変数(UNIXの場合CLASS_CACHE=true
、Windowsの場合set CLASS_CACHE=true
)を設定します。
次のプロパティを使用して、クラス・キャッシュを構成します。
ロギング: クラス・キャッシュの問題をデバッグするには、キャッシュを有効にする起動スクリプトの項に対して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のクラス・ロードは、アプリケーションの概念に基づいています。アプリケーションは、通常、アプリケーション・クラスを含むエンタープライズ・アーカイブ(EAR)ファイルにパッケージ化されています。EARファイル内にあるものは、すべて同じアプリケーションの一部と見なされます。次のファイルは、EARの一部になることもでき、またスタンドアロンのアプリケーションとしてロードすることも可能です。
Enterprise JavaBeans (EJB) JARファイル
WebアプリケーションWARファイル
リソース・アダプタRARファイル
注意: 詳細については、次の各項を参照してください。
|
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アプリケーションのクラス・ロード概念を示しています。
アプリケーションに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クラス・ローダーを示していません。
この階層は、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.xml
のclassloader-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>
ネスティングの構成は、クラス・ローダーの階層を示します。上記のスタンザにより、次の図に示す階層がもたらされます。
ユーザー定義のクラス・ローダーの制約により、再ロードの対象とモジュール間でのクラスの可視性が制御しやすくなります。この機能は主に開発者用です。繰返し開発が行われる場合には有用ですが、本番環境で使用する目的の場合には再ロード機能の使用はお薦めしません。更新時に無効な要素が含まれると、実行中のアプリケーションが破損するおそれがあるためです。ネームスペースの分離とクラス参照のためのカスタム・クラス・ローダーの配置は、本番環境で使用する場合においても容認できるものです。ただし、Java EE仕様にはアプリケーションがいかなるクラス・ローダー構成にも依存してはならないと書いてあることに、プログラマは注意する必要があります。
一部のクラス・ローダー階層は、アプリケーション内のモジュールが2つの別個のアプリケーションのモジュールのように動作する原因となる可能性があります。たとえば、EJBを独自のクラス・ローダーに配置して個別に再ロードできるようにすると、Oracleが標準的なクラス・ローダー階層に提供しているcall-by-referenceによる最適化ではなく、call-by-valueセマンティクスを受け取ります。また、カスタム階層を使用すると、参照が古いものになる可能性があります。したがって、EJBモジュールを再ロードする場合は、呼出し側モジュールも再ロードしてください。
ユーザー定義によるモジュール・クラス・ローダー階層の作成には、いくつかの制約があります。これらについてはこれ次の項で説明します。
標準のWebLogic Serverクラス・ローダー階層により、EJBインタフェースがアプリケーション内のすべてのモジュールで利用可能になります。したがって、それ自体のモジュールにインタフェースが含まれていなくても、他のモジュールがEJBを呼び出せます。これが可能なのは、EJBは常にルート・クラス・ローダーにロードされ、その他のモジュールはすべてそのクラス・ローダーを共有するか、そのクラス・ローダの子に相当するクラス・ローダーを持つことになるためです。
カスタム・クラス・ローダー機能があれば、呼び出される側のクラスが呼出し側から見えないようにクラス・ローダー階層を構成することが可能です。この場合、呼出し側モジュールにインタフェース・クラスを含める必要があります。これは、別個のアプリケーションのモジュールに対して呼出しを行っている場合の要件と同じです。
WebLogic Serverに設けられた標準クラス・ローダー階層により、アプリケーション内のモジュール間での呼出しでcall-by-referenceセマンティクスを使用することが可能となります。これは、呼出し側が常に同じクラス・ローダーまたは呼び出される側の子クラス・ローダーを使用しているためです。この機能により、2つのモジュールがクラス・ローダー・ツリーにおける別々のブランチに存在するように、クラス・ローダー階層を構成することが可能になります。この場合、call-by-valueセマンティクスが使用されます。
再ロードに必要となるクラス・ローダーの切替えは、複数モジュールに渡って原子性を保たないことに留意してください。実際、アプリケーションの更新は、一般に原子性を保ちません。この理由により、タイミングによっては、異なった処理中の操作(変更が行われているときに発生している操作)が、異なったバージョンのクラスにアクセスすることになる可能性があります。
WebLogic Serverを使うと、他のモジュールを同時に再ロードして、EJBモジュール全体を再デプロイする必要なしに、個々のEJBモジュールを再ロードできます。この機能は、現在JSPがWebLogic Serverサーブレットのコンテナに再ロードされている方法に類似しています。
EJBクラスはインタフェースを通じて呼び出されるため、個々のEJB実装クラスをそれ自身のクラス・ローダーにロードすることが可能です。このようにして、これらのクラスはEJBモジュール全体を再デプロイすることなく個別に再ロードできます。次の図は、単一のEJBモジュールのクラス・ローダー階層の一例です。2つのEJB (Foo
およびBar
)が含まれています。これは、前の項で説明した一般的なアプリケーション階層におけるサブツリーと考えられます。
展開されたアプリケーションのルートを基準とした相対的な場所にあるファイルの部分的な更新を実行するには、次のコマンド・ラインを使用します。
例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
はアプリケーション・クラス・ローダーとシステム・クラス・ローダーの間に位置します。システム・クラス・ローダーの子であり、アプリケーション・クラス・ローダーの親となります。FilteringClassLoader
はloadClass(String
className
)
メソッドをインターセプトして、weblogic-application.xml
ファイルに指定されているパッケージのリストとclassName
を比較します。パッケージとclassName
が一致する場合、FilteringClassLoader
はClassNotFoundException
をスローします。この例外は、このクラスをアプリケーションからロードするようにアプリケーション・クラス・ローダーに通知します。
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.ClassLoader
のgetResource()
および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とは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の使用を開始するには:
WebLogic Server管理コンソールで、「デプロイメント」 > 「app_name」 > 「テスト」を選択し、「クラス・ローダー分析ツール」リンクを選択します。コンソールのログイン資格証明情報を入力します。
あるいは、ブラウザを開いてhttp://wls-host:port/wls-cat/
へ移動し、コンソールのログイン資格証明情報を入力します。
CATに搭載された単純なWeb GUIに現在実行中のアプリケーションやモジュールがすべて表示されます。左側のナビゲーション・ペインで、分析するアプリケーションまたはモジュールを選択します。その簡単な説明が右側のペインに表示されます。右側のペインを使用し、選択したアプリケーションまたはモジュールに対してアクションや分析を実行します。CATでは次の操作を実行できます:
クラス・ロード競合状態の分析
システムおよびアプリケーションのクラス・ロードの表示
レポートの生成
CATは、システム・クラスパス・クラス・ローダーやWebLogic Serverのメイン・アプリケーションのクラス・ローダーによってロードされ、フィルタリング、アプリケーション、およびモジュールのクラス・ローダーとして定義されたクラスを分析します。クラス、パッケージ、またはJARのレベルで分析を実行できます。選択する各アクションの結果は、基本ビューまたは詳細ビューで表示されます。
CATを使用して実行できるタスクの例を紹介します。
アプリケーションおよびモジュールに関する基本情報の表示
クラス・ロード競合状態の分析
提案されたソリューションの確認
フィルタリング・クラス・ローダーの構成に関する提案の取得
クラス・ローダー階層および各クラス・ローダーのクラスパス全体の表示
クラス・ローダーにおけるクラス(またはリソース)の検索
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を共有するには:
ドメイン内のすべてのサーバーを停止します。
共有する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 ディレクトリに読込みアクセスできるようにする必要があります。
管理サーバーは、 |
ドメイン内の管理サーバーとすべての管理対象サーバーを起動します。