5.3.4 メソッドキャンセルとは
メソッドキャンセルとは,タイムアウトの原因となっている実行中の処理をキャンセルする処理です。メソッドキャンセル時には,現在実行されている処理がキャンセルできるかどうかを判断します。
- ポイント
-
Connector 1.5仕様に準拠したリソースアダプタを使用している場合,次の処理はメソッドキャンセルの対象にできません。
-
リソースアダプタ独自のメソッド
-
ワーク管理で実行されているWork
ただし,Workによって呼び出されたMessage-driven Bean内の処理については,メソッドキャンセルの対象にできます。
-
- 〈この項の構成〉
(1) 保護区と非保護区
メソッドをキャンセルできる領域のことを非保護区,メソッドをキャンセルできない領域を保護区といいます。
保護区とは,メソッドキャンセルのできない領域です。保護区では,J2EEサーバの動作で共有されるデータや領域を保持したり,JavaVM内で行われる処理を保証したりするため,メソッドキャンセルができません。J2EEサービス,Webコンテナ,EJBコンテナが保護区に該当します。保護区として定義されている内容については,「付録C 保護区リストの内容」を参照してください。ここに記載されている保護区に該当するクラス以外で,保護区として扱いたいクラスがある場合は,保護区リストファイルに記述してください。
一方,非保護区は,メソッドキャンセルができる領域です。J2EEアプリケーションが非保護区になります。
保護区,非保護区の判定は,クラス単位で行われます。ただし,非保護区の場合は実行時の条件によって保護区として扱われることがあります。J2EEアプリケーションでも,ネイティブメソッドを呼び出している場合や,スタティックイニシャライザを実行している場合は,保護区と判定されます。また,java.lang.Objectクラスのwaitメソッドは,スタティックイニシャライザの延長での呼び出しではない場合だけ,例外的に非保護区と判定されます。※
注※ java.lang.Objectクラスのwaitメソッドは,指定時間の経過やnotify/notifyAllによって処理が再開される時に,スレッドのモニタ(ロック)を取得します。このモニタ取得待ちの間に保護区の判定を行った場合は,非保護区と判定されますが,実際にキャンセルが実行されるのはスレッドのモニタを取得した直後となります。
(2) メソッドキャンセルの処理
メソッドキャンセルは,現在実行中の処理が非保護区の場合だけ実行されます。メソッドキャンセルができるかどうかを確認するため,保護区の判定では,キャンセル対象となるメソッドが非保護区で実行中かどうかを判定します。実行している処理が非保護区の場合は,メソッドキャンセルが行われます。保護区の場合は,一定間隔で保護区の判定をリトライします。判定処理で保護区と判定されるたびに,KDJE52718-Wのメッセージが出力されます。一定時間内に非保護区に制御が移らない場合は,メソッドキャンセルが失敗したと見なされ,メソッドキャンセルの処理が終了します。
保護区の判定処理の流れを次の図に示します。
なお,メソッドキャンセル時には,次の処理が実施されます。
-
トランザクションを開始している場合は,トランザクションが強制的にタイムアウトされ,ロールバックにマークされます。
-
SQLを実行中でステートメントキャンセル機能が有効な場合は,SQLがキャンセルされます。
上記の処理は,保護区を実行中のためにメソッドキャンセルが行われない場合も実施されます。
トランザクションタイムアウトの詳細については,マニュアル「アプリケーションサーバ 機能解説 基本・開発編(コンテナ共通機能)」の「3.15.8 トランザクションタイムアウトとステートメントキャンセル」を参照してください。
(3) WebコンテナおよびEJBコンテナでのメソッドキャンセル時の動作
メソッドキャンセルを実行すると,キャンセル対象となるメソッドを実行中のスレッドで,ThreadDeathが発生します。WebコンテナおよびEJBコンテナでは,このThreadDeathをキャッチして必要な処理を実施します。
WebコンテナおよびEJBコンテナでのメソッドキャンセル時の動作について説明します。
(a) Webコンテナでの動作
ThreadDeathがスローされるタイミングによって動作が異なります。
- Webアプリケーションのフィルタ/サーブレット/JSPでのリクエスト処理中にThreadDeathがスローされた場合
-
呼び出し元となるフィルタ/サーブレット/JSPにjavax.servlet.ServletExceptionがスローされます。
例えば,フィルタからjavax.servlet.FilterChainのdoFilterメソッド呼び出しの延長でサーブレットが実行され,そのサーブレットの実行中にThreadDeathが発生した場合,doFilterメソッドの呼び出しで,javax.servlet.ServletExceptionがスローされます。
同様に,javax.servlet.RequestDispatcherのforwardメソッド,またはincludeメソッドを呼び出して,リクエストをサーブレット/JSPに転送した場合,javax.servlet.ServletExceptionのgetRootCauseメソッドでは,ThreadDeathオブジェクトを返します。
- Webアプリケーションのリスナの処理中にThreadDeathがスローされた場合
-
WebコンテナはThreadDeathをキャッチしますが,リスナが呼び出される契機となったイベントの発生元となるユーザプログラム処理に対しては,例外はスローされません。
例えば,javax.servlet.http.HttpServletRequestのgetSessionメソッドの呼び出しによってHttpSessionを作成した場合,javax.servlet.http.HttpSessionListenerのsessionCreatedメソッドが呼び出されます。このsessionCreatedメソッドの実行中にThreadDeathがスローされた場合,WebコンテナはスローされたThreadDeathをキャッチしますが,HttpSession生成のイベントを発生させたgetSessionメソッド呼び出しには例外をスローしません。
(b) EJBコンテナでの動作
EJBのメソッド呼び出し中にThreadDeathがスローされた場合は,EJB仕様で定められたシステム例外が発生した場合と同等の動作をします。呼び出し元に返る例外のgetCauseメソッドでは,ThreadDeathオブジェクトを返します。
(4) メソッドキャンセル実行のタイミング
メソッドキャンセル実行のタイミング,およびメソッドキャンセル実行までに掛かる最大の時間について説明します。
-
タイムアウト発生時
メソッドタイムアウト時のメソッドキャンセルのモードとして,スレッドを停止することが設定されている場合,タイムアウト発生時にメソッドキャンセルが実行されます。メッセージを出力するだけの設定の場合は,タイムアウト時でもメソッドキャンセルは実行されません。
タイムアウトが発生したメソッドのキャンセル処理は,一定の間隔で実行されます。また,メソッドキャンセルの処理は,動作中のリクエスト処理がタイムアウトしていないかを調査する(タイムアウトを監視する)スレッドとは別のスレッドで,非同期で実行されます。そのため,タイムアウトの検知後にメソッドキャンセルが実行されるまでには,最大で,メソッドキャンセル処理の時間間隔分掛かります。
メソッドキャンセル処理の時間間隔は,タイムアウトを監視する時間間隔と同じです。メソッドキャンセル処理の時間間隔の設定については,「5.3.9 実行環境での設定」を参照してください。
-
メソッドキャンセルコマンドの実行時
運用中にメソッドキャンセルコマンドを実行すると,メソッドキャンセルが実行されます。
メソッドキャンセルコマンドは,タイムアウトが発生したメソッドを実行中のスレッドの状態を確認して,メソッドキャンセルが実行できることを確認してから,必要に応じて実行します。
メソッドキャンセルを実行するための手順については,「5.3.10 J2EEアプリケーションの実行時間の監視とキャンセルの流れ」を参照してください。
メソッドキャンセル処理は,コマンド実行後に非同期に実行されます。また,メソッドキャンセル処理は,メソッドキャンセル処理の時間間隔には影響されません。
-
J2EEアプリケーション強制停止の実行時
J2EEアプリケーションを強制停止した場合に,停止対象となるJ2EEアプリケーションで実行中のスレッドがあるときは,メソッドキャンセルが実施されます。
アプリケーションの強制停止については,「5.5.4 強制停止処理とは」を参照してください。
メソッドキャンセル処理は,コマンド実行後に非同期で実行されます。また,メソッドキャンセル処理は,メソッドキャンセル処理の時間間隔には影響されません。
(5) メソッドキャンセル時の注意事項
メソッドキャンセル時,デフォルトではローカル変数情報がスタックトレースに出力されます。
性能への影響が出るおそれがあるため,メソッドキャンセル時にローカル変数情報をスタックトレースに出力しないように,JavaVM拡張オプションの「-XX:-HitachiLocalsInStackTrace」の設定を推奨します。