18.8.13 リロードの注意事項および制限事項
リロードに関する注意事項および制限事項を次に示します。
- 〈この項の構成〉
(1) リロード機能の使用に関する注意事項
-
J2EEアプリケーションの削除について
リロードに失敗しているJ2EEアプリケーションを削除する場合は,次のどちらかの方法で削除してください。
-
更新検知によるリロード,またはcjreloadappコマンドによるリロードを再度実行してください。リロードが成功したら,J2EEアプリケーションを停止して削除してください。
-
J2EEサーバを再起動したあとで,J2EEアプリケーションを削除してください。
削除後,J2EEアプリケーションを再インポートしてください。
-
-
メモリ不足の発生について
リロード処理では,クラスローダを再作成してクラスをロードし直すため,メモリを多く消費します(消費するメモリ使用量は,J2EEアプリケーションの実装に依存します)。このため,例えば,複数のWebアプリケーションで同時にリロード処理を繰り返すとメモリ不足が発生する可能性があります。また,リロード処理によって不要となったリソースがJavaVMから解放されるタイミングは,JavaVMのGCの実行タイミングに依存します。リクエストのピーク時など,負荷が高いときにリロードを繰り返すと,GCを実行するタイミングがなく,メモリ不足が発生する可能性が高くなります。
このため,リクエストのピーク時など負荷が高い場合には,リソースの更新は避けてください。
-
Metaspace領域のメモリサイズについて
リロードを使用する場合,Metaspace領域に空きがない状態で新しいクラスをロードしようとすると,java.lang.OutOfMemoryErrorが発生します。そのため,リロード実行前に,Metaspace領域に更新するアプリケーションが使用するサイズ以上の空き領域が確保されていることを確認する必要があります。十分な空き領域がない場合は,Metaspace領域が不足しているおそれがあるので,Metaspace領域の最大値を再設定してください。
リロード実行時には,アプリケーションのクラスローダを破棄し,新しいクラスローダを生成します。そのとき,JavaVMの仕様とクラスローダの実装によって,破棄されたクラスローダは直ちに解放されないことがあります。その結果,リロード実行後は一時的にアプリケーションが必要とするサイズ以上にMetaspace領域が占有されます。そのため,リロード機能が必要とするMetaspace領域は,アプリケーションが必要とするMetaspace領域の3倍程度に見積もることをお勧めします。
Metaspace領域の見積り式を次に示します。
A=B+C+(D×3)+G
-
A:J2EEサーバが必要とするMetaspace領域
-
B:コンテナが必要とするMetaspace領域(120メガバイト)
-
C:コンテナ拡張ライブラリが必要とするMetaspace領域
コンテナ拡張ライブラリに含まれるclassファイルのサイズの和となります。
-
G:JDK提供のclassファイルのサイズ(90メガバイト)
-
D:アプリケーションが必要とするMetaspace領域
クラスローダにロードされたクラスのclassファイルのサイズとなります。ただし,JARファイルに圧縮されているclassファイルは,解凍後のサイズで見積もる必要があります。また,アプリケーションにJSPが含まれている場合,JSP事前コンパイルを実行してclassファイルを作成し,サイズを見積もる必要があります。見積もり式を次に示します。
D=E+F+H
・E:コンテナが作成するクラスのMetaspace領域(アプリケーション開始後のMetaspace領域−アプリケーション登録前のMetaspace領域)。実際にJ2EEサーバを起動し,Metaspace領域を確認して算出してください。
・F:作成したJ2EEアプリケーションのclassファイルのサイズ(J2EEアプリケーションを構成するclassファイルのサイズ+JARに含まれるclassファイルのサイズ+JSP事前コンパイルによって作成されたclassファイルのサイズ)
・H:ライブラリJAR,参照ライブラリを利用している場合に追加するJARファイルに含まれるclassファイルのサイズ
- Metaspace領域の見積り例と変更例
-
各Metaspace領域のメモリサイズが次の表に示す値の場合に,Metaspace領域の最大値を変更する例を示します。
見積もり対象となるMetaspace領域
メモリサイズ(単位:メガバイト)
コンテナが必要とするMetaspace領域
120
追加するJARファイルが必要とするMetaspace領域
16
アプリケーションが必要とするMetaspace領域
32
JDK提供のclassファイルのサイズ
90
この例では,J2EEサーバが必要とするMetaspace領域は,次の式で算出します。
120+16+(32×3)+90=322(メガバイト)
したがって,リロード機能を使用する場合は,割り当てるMetaspace領域の最大値のデフォルト(128m)を,usrconf.cfgのadd.jvm.argキーで次のように変更する必要があります。
add.jvm.arg=-XX:MaxMetaspaceSize=322m
- Metaspace領域の確認方法
-
Metaspace領域のメモリサイズは,JavaVMログファイルを出力するか,またはリソース枯渇監視機能を使用するか,どちらかの方法で確認してください。
-
-
メソッドキャンセルの実行について
処理中のリクエストの処理が完了しない場合には,J2EEアプリケーション実行時間の監視のメソッドタイムアウトおよびメソッドキャンセルを実行することで,リロード処理を開始できます。メソッドキャンセルを実行しても,処理をキャンセルできない場合には,J2EEサーバを再起動してください。
-
実行待ちとなっているリクエスト処理の再開について
J2EEアプリケーションのリロードでEJBアプリケーションの開始,または停止に失敗した場合,Webアプリケーションのリロード処理開始以降の新規リクエストは実行待ちとなります。実行待ちとなっているリクエスト処理を再開するためには,EJBアプリケーションを更新してリロードを実行し,リロード処理を成功させてください。Webアプリケーションを更新しても,リロードは実行されません。
-
J2EEアプリケーションに含まれるRARファイルについて
アプリケーションディレクトリにRARファイルを含めている場合,RARファイルはリロード機能の対象にはなりません。RARファイルを更新した場合は,更新したRARファイルを含むJ2EEアプリケーションを,サーバ管理コマンドを使用して入れ替えてください。サーバ管理コマンドを使用してJ2EEアプリケーションを入れ替える手順については,マニュアル「アプリケーションサーバ 機能解説 運用/監視/連携編」の「5.6 J2EEアプリケーションの入れ替え」を参照してください。
-
CDI機能を使用したJ2EEアプリケーションのリロードについて
J2EEアプリケーション内のコンポーネント(EJB-JAR,ライブラリJAR,WAR)にCDIの機能を含む場合,更新検知によるリロードはできません。リロードを実行するには,cjreloadappコマンドを使用してください。更新検知によるリロードが有効な設定の場合,CDIの機能を使用したJ2EEアプリケーションの開始時にKDJE42393-Wが出力され,更新検知によるリロードが無効であることが通知されます。
CDIの機能を使用したJ2EEアプリケーションをリロードするには,簡易構築定義ファイルの論理J2EEサーバ(j2ee-server)の<configuration>タグ内で,ejbserver.deploy.context.reload_scopeパラメタに「app」を設定してください。リロードを実行すると,更新したファイルがWARファイルまたはJSPファイルの場合でも,J2EEアプリケーションすべてがリロードされます(WAR単位,またはJSP単位でのリロードはできません)。このとき,更新したファイルがWARファイルまたはJSPファイルの場合,KDJE42395-Iが出力され,J2EEアプリケーションすべてがリロードされることが通知されます。
CDIの機能を使用したJ2EEアプリケーションに対してcjreloadappコマンドを実行してリロードした際に,簡易構築定義ファイルの論理J2EEサーバ(j2ee-server)の<configuration>タグ内で,ejbserver.deploy.context.reload_scopeパラメタに「web」または「jsp」を指定していた場合は,KDJE42394-Eが出力され,リロードに失敗します。
プロパティejbserver.javaee.cdi.beanIdentifierIndexOptimizationにtrueを指定して,効率的にCDI管理Beanの識別IDにアクセスにする機能を有効にすると,CDIが有効なアプリケーションに対してのリロードでエラーが発生するおそれがあります。
CDIが有効なアプリケーションに対してのリロードをする場合は,プロパティejbserver.javaee.cdi.beanIdentifierIndexOptimizationにfalse(デフォルト値)を指定してください。
CDIの機能を使用したJ2EEアプリケーションに,cjreloadappコマンドを実行してリロードした場合の実行結果を次の表に示します。
表18‒20 cjreloadappコマンドの実行結果(CDIの機能を使用したJ2EEアプリケーション) 更新したファイルを含むコンポーネント
ejbserver.deploy.context.reload.scopeパラメタの値
cjreloadappコマンドの実行結果
EJB-JARまたはライブラリJAR
app
J2EEアプリケーションすべてがリロードされる。
web
KDJE42394-Eが出力され,コマンドの実行に失敗する。
jsp
WAR
app
KDJE42395-Iが出力され,J2EEアプリケーションすべてがリロードされる。
web
KDJE42394-Eが出力され,コマンドの実行に失敗する。
jsp
JSP
app
KDJE42395-Iが出力され,J2EEアプリケーションすべてがリロードされる。
web
KDJE42394-Eが出力され,コマンドの実行に失敗する。
jsp
-
Inboundリソースアダプタについて
アプリケーションのリロード中は,Inboundリソースアダプタからメッセージを送信しないでください。
-
Message-driven Beanのリロードについて
TP1インバウンド連携機能使用時にMessage-driven Beanをリロードする場合は,OpenTP1からのRPCの発行を止めてからリロードしてください。リロード中にRPCを発行した場合は,Message-driven Beanは終了していると見なされ,RPCの発行元にはエラー応答が返ります。
(2) EJBアプリケーション(EJB-JAR)の注意事項
-
リロード後にEJBを呼び出す場合には,クライアント側のソースコードでEJBHomeやビジネスインタフェースを取得し直す必要があります。リロード前に取得したインタフェース経由でEJBにアクセスした場合は例外が返ります。また,リロード実行中にEJBにアクセスした場合も例外が返ります。
-
リモートインタフェースまたはリモートビジネスインタフェースを入れ替えた場合,クライアント側ではスタブを取得し直す必要があります。
-
リロードを実行すると,Stateful Session Beanのクライアントとのセッションの状態は失われます。
-
非同期メソッドを展開ディレクトリ形式のJ2EEアプリケーションでリロード機能を使用する場合,次の点に注意してください
-
非同期メソッドが実行中の場合,非同期メソッドの処理が完了するまで,リロード処理は待機します。
-
リロード処理では,クリーンアップ処理が実行されるため,リロード処理前に取得したFuture<V>オブジェクトによる操作は実行できなくなります。
-
-
Singleton Session Beanを含む展開ディレクトリ形式のJ2EEアプリケーションをリロードする場合,次の点に注意してください。
-
@Startupアノテーションが指定されたSingleton Session Beanは,アプリケーション開始時と同様に,リロード時にも初期化処理が実行されます。
-
リロード処理の間,リロード対象のJ2EEアプリケーション内のSingleton Session Beanのインスタンスはコンテナによって破棄されます。
-
@DependsOnアノテーションの定義によって,リロードするSingleton Session Beanの依存関係を変更できます。ただし,循環依存があった場合も,リロード処理ではエラーになりません。このため,リロードの対象となるSingleton Session Beanでは,循環依存を避けるため,@DependsOnアノテーションの使用を避けることをお勧めします。@DependsOnアノテーションを使用して,循環依存があった場合,動作は保証されません。
-
Writeロックを取得待ちの状態のスレッドの処理は,リロード処理によって中断されません。
-
(3) EJBアプリケーション(EJB-JAR)の制限事項
-
これまでjavax.ejb.TimedObjectインタフェースを実装していなかったEJBで,javax.ejb.TimedObjectインタフェースを実装するように変更して,リロードすることはできません。リロードした場合には,次のようになります。
-
更新検知スレッドは停止させないで,J2EEアプリケーションを停止します。
-
更新を検知した場合,停止したJ2EEアプリケーションは再び開始されます。
-
-
CMRを使用したアプリケーションはリロードできません。
-
Singleton Session Beanの@DependsOnアノテーションの設定値を変更してリロードした場合,設定された依存関係が循環関係になっているときはリロードできません。
(4) Webアプリケーション(WAR)の注意事項
-
タグライブラリ記述子ファイルのlistenerタグの変更内容は,リロード後に反映されません。
-
リロード時に利用できるサーブレットとJSPは,リロード後も状態を継続して利用できます。永久的に利用できないとされている場合は,リロード後も永久的に利用できません。一時的に利用できない場合は,リロードの実行とは関係なく,指定した期間後に利用できるようになります。
-
Webアプリケーションでリロード監視対象になっているファイルを削除した場合,そのファイルは監視対象外となります。このため,再度ファイルを追加しても更新検知によるリロードは実行されません。ただし,/WEB-INF/lib下にJARファイルを追加した場合は,そのJARファイルが削除後に再度追加されたかどうかに関係なく,コマンドによるリロードまたは更新検知によるリロードを実行できます。
-
JSPのリロード処理中にJ2EEアプリケーションを停止した場合,またはWebアプリケーションをリロードした場合,JSPのリロード処理は中止されます。
-
JSPのリロード処理開始時,ログの出力レベルがErrorの場合は,メッセージKDJE39310-Iに,更新されたファイル名とリロードを実行するJSPファイルのファイル数が出力されます。ログの出力レベルがWarningの場合は,メッセージKDJE39312-Iに,リロードを実行するすべてのJSPファイル名が出力されます。
-
リスナクラスのロード,インスタンス生成時に例外が発生した場合,Webコンテナは例外が発生したリスナを無効としてリロード処理を続行します。例外が発生したリスナを有効にするには,該当のリスナを修正して再度リロードを実行してください。
-
フィルタクラスのロード,インスタンス生成,initメソッド実行で例外が発生した場合,Webコンテナは例外が発生したフィルタを無効としてリロード処理を続行します。例外が発生したフィルタを有効にするには,該当のフィルタを修正して再度リロードを実行してください。
-
Webアプリケーションのリロード処理を実行すると,次の表に示すリスナインタフェースのメソッドが実行されます。
表18‒21 Webアプリケーションのリロード処理で実行されるリスナのメソッド インタフェース名
メソッド名
javax.servlet.ServletContextListener
contextDestroyed()
contextInitialized()
javax.servlet.ServletContextAttributeListener
attributeRemoved()
attributeAdded()
javax.servlet.http.HttpSessionActivationListener※
sessionWillPassivate()
sessionDidActivate()
-
リロード処理時間は,Webアプリケーションの実装に大きく依存します。このため,次の点に注意が必要です。
-
セッション情報の容量は,シリアライズ処理時間,デシリアライズ処理時間に大きく影響します。シリアライズ対象となるセッション情報は,必要十分な容量にしてください。
-
リロード処理では,Webアプリケーションの終了処理,初期化処理が実行されます。終了処理,初期化処理が長い場合,リロードの処理時間も長くなり,Webアプリケーションのサービス停止期間にも影響があるため注意してください。ただし,リロード処理で初期化処理が実行されるのは,web.xmlの<load-on-startup>タグを設定したサーブレットやJSPだけです。<load-on-startup>タグを設定していないサーブレットやJSPの初期化処理は,リロード完了後の初回アクセス時に実行されます。
-
-
Webアプリケーションのリロード機能は,Webアプリケーション単位のクラスローダを入れ替えることによって,サーバ起動中のWebアプリケーションの入れ替えを実現しています。そのため,リロード後にリロード前のWebアプリケーション単位のクラスローダ,またはWebアプリケーション単位のクラスローダでロードされたクラスが参照されるとメモリリークが発生します。
次に,該当する場合を示します。リロード機能を使用する場合は,Webアプリケーション内でこれらのことをしないでください。
-
スレッドの生成
スレッドはコンテキストクラスローダを保持しますが,デフォルトでは親スレッドのコンテキストクラスローダを保持します。Webアプリケーション実行時のスレッドは,Webアプリケーション単位のクラスローダをコンテキストクラスローダとしているため,生成されたスレッドはWebアプリケーション単位のクラスローダをコンテキストクラスローダとします。そのため,リロード後も該当スレッドが存在すると,リロード前のWebアプリケーション単位のクラスローダが解放されないでメモリリークが発生します。
-
java.lang.Threadクラスまたはその派生クラスのインスタンス生成
java.lang.Threadクラスまたはその派生クラス(以降,スレッドクラス)のインスタンスを作成すると,所属するスレッドグループから該当スレッドクラスのインスタンスが参照されます。スレッドグループからの参照は,スレッドの実行を終了(runメソッドの完了)すると解放されます。そのため,Webアプリケーション内でスレッドクラスのインスタンスを生成し,runメソッドを実行しなかった場合は,該当スレッドクラスのインスタンスが解放されません。また,スレッドはコンテキストクラスローダとしてWebアプリケーション単位のクラスローダを保持しているため,Webアプリケーション単位のクラスローダが解放されないでメモリリークが発生します。
-
スレッドローカル変数の使用
Webコンテナではリクエストを処理するスレッドはプールされていて,Webコンテナ終了時まで終了しません。そのため,スレッドローカル変数にWebアプリケーションに含まれるクラスのインスタンスを格納すると,メモリリークが発生します。
-
-
JSP事前コンパイル機能を使用している場合,JSPファイルまたはタグファイルが依存するファイルは更新検知対象となったあと,次のどれかの条件を満たすときに更新検知対象から除外されます。
-
JSPファイルまたはタグファイルを,依存するファイルを使用しないように変更したクラスファイルに更新し,依存するファイルを使用するJSPファイルまたはタグファイルがほかにはない場合
-
JSPファイルまたはJSPファイルが依存するファイルから生成されたクラスファイルを更新し,JSPファイルから生成されたクラスのロードでエラーが発生した際,依存するファイルを使用するJSPファイルまたはタグファイルがほかにはない場合
該当するファイルが更新検知対象から除外された場合,メッセージログにKDJE39319-Iが出力されます。
なお,cjjspcコマンドを実行すると依存するファイルを使用しているJSPファイルまたはタグファイルも再度コンパイルされます。クラスファイルを展開ディレクトリ以外で作成したあとに更新する場合は,cjjspcコマンドで生成されたクラスファイルをすべて更新してください。
-
-
JSP事前コンパイル機能を使用していない場合,JSPファイルまたはタグファイルが依存するファイルは更新検知対象となったあと,次のどれかの条件を満たすときに更新検知対象から除外されます。
-
JSPファイルまたはタグファイルを,依存するファイルを使用しないように修正し,コンパイルが正常に完了した際,依存するファイルを使用するJSPファイルまたはタグファイルがほかにはない場合
-
JSPファイル,またはJSPファイルが依存するファイルを更新し,JSPファイルのコンパイルエラーが発生した際,依存するファイルを使用するJSPファイルまたはタグファイルがほかにはない場合
該当するファイルが更新検知対象から除外された場合,メッセージログにKDJE39318-Iが出力されます。また,JSPファイルのコンパイルエラーが発生し,かつ次の条件を満たすときは,更新検知対象から除外されたファイルだけを修正することで,コンパイルエラーとなったJSPファイルを修正しないで,JSPのリロードを実行できます。
-
依存するファイルがタグファイルの場合
タグファイルの記述内容とタグファイルを使用するファイルの記述内容が矛盾している。タグファイルの次の属性のどれかが不正である。
tagディレクティブに定義した属性:body-content,またはdynamic-attributes
attributeディレクティブに定義した属性:name,required,fragment,rtexprvalue,またはtype
variableディレクティブに定義した属性:name-given,variable-class,declare,またはscope
-
依存するファイルがweb.xmlの<include-prelude>,または<include-coda>に指定した暗黙的にincludeされるファイルの場合
暗黙的にincludeされたファイルの記述内容が,includeするJSPファイルの記述内容と矛盾している。
-
依存するファイルがincludeディレクティブに指定したファイルの場合
includeディレクティブに指定されたファイルの記述内容が,includeディレクティブを指定したJSPファイルまたはタグファイルの内容と矛盾している。
-
依存するファイルがタグライブラリ・ディスクリプタ(TLD)ファイルの場合
TLDファイルの記述内容とJSPファイルの記述内容が矛盾している。
この場合,該当するファイルは更新検知の対象外となっているため,依存するファイルを更新したあと,次のどれかを実行しJSPのリロードを実行する必要があります。
-
依存するファイルを使用するJSPファイルにブラウザなどからアクセスする。
-
依存するファイルを使用するJSPファイルまたはタグファイルの更新日時を更新する。
-
-
implicit.tldは更新検知対象ファイルではありません。implicit.tldとは,Servlet2.5仕様で定義されたタグファイルのバージョンを示すTLDファイルです。implicit.tldはJSP,またはタグファイルのリロード時に同時に再読み込みされます。
-
Webアプリケーションのリロードでは,アノテーション情報は読み込みません。Webアプリケーションのクラスに定義したアノテーション情報だけを更新した場合,その更新情報を反映するには,J2EEアプリケーションをいったん停止して再度開始してください。