2.3.11 バッチアプリケーション作成時の注意
ここでは,バッチアプリケーション作成時に注意が必要となる処理や,バッチアプリケーションでは使用できない機能について説明します。これらの内容を確認の上,バッチアプリケーションを作成してください。
(1) 注意が必要な処理
次に示す処理は,バッチアプリケーションを作成する際に注意が必要です。
(a) ファイルやディレクトリの操作
バッチアプリケーションでは,次に示すファイルやディレクトリは操作しないでください。
-
Application Serverのインストールディレクトリ以下のファイルやディレクトリ
Application Serverのインストールディレクトリ以下のファイルやディレクトリについては,マニュアル「アプリケーションサーバ システム構築・運用ガイド」の「付録B インストール後のディレクトリ構成」を参照してください。
-
バッチサーバの作業ディレクトリ以下のファイルやディレクトリ
バッチサーバの作業ディレクトリについては,マニュアル「アプリケーションサーバ システム構築・運用ガイド」の「付録C.2 バッチサーバの作業ディレクトリ」を参照してください。
また,バッチアプリケーションでファイルやディレクトリを扱う場合,ファイルやディレクトリのパスに相対パスを使用できません。cjexecjobコマンドを実行したディレクトリからの相対パスを取得したい場合は,ejbserver.batch.currentdirの値を使用してください。ejbserver.batch.currentdirについては,マニュアル「アプリケーションサーバ リファレンス API編」の「ejbserver.batch.currentdirプロパティ」を参照してください。
次に,バッチアプリケーションの修正例を示します。
- 修正前
File f = new File("DataFile.txt");
- 修正後
File f = new File(System.getProperty("ejbserver.batch.currentdir") + System.getProperty("file.separator") + "DataFile.txt");
(b) スレッドの使用
バッチサーバは,バッチアプリケーションが作成および開始したスレッドの終了を待ちません。バッチアプリケーション内でスレッドを使用する場合は,バッチアプリケーションを終了する前に,開始したすべてのユーザスレッドを完了するように実装してください。また,ユーザスレッドはメソッドキャンセルの対象外です。
なお,簡易構築定義ファイルでejbserver.batch.application.exit.enabledパラメタで「true」を指定した場合には,次の点に注意してください。
-
スレッドグループ(ThreadGroup)を作成できません。
-
バッチアプリケーションにjava.lang.ThreadクラスのインタフェースであるUncaughtExceptionHandlerを継承したハンドラを登録していると,JavaVM終了メソッド呼び出し時に登録したハンドラの処理が実行されます。このとき,uncaughtExceptionメソッドの引数にJP.co.Hitachi.soft.jvm.SpecialThrowableの例外が渡されることがあります。
バッチアプリケーションが作成したスレッドが残っていると,バッチアプリケーションのクラスや使用したリソースは解放されません。このため,次にバッチアプリケーションを開始しようとすると,バッチアプリケーションの開始に失敗するおそれがあります。また,ユーザスレッド内では,次のバッチサーバの機能を呼び出すことはできません。
-
バッチアプリケーション実行機能
-
EJBアクセス機能
-
ネーミング管理が提供する機能
-
リソース接続とトランザクション管理が提供する機能
-
GC制御機能
-
コンテナ拡張ライブラリが提供する機能
(c) JavaVM終了時のリソースの自動クローズ
バッチサーバではサーバのJavaVM上でバッチアプリケーションを実行します。このため,JavaVM終了による自動的なリソースのクローズ処理を期待した実装をしている場合は,メモリやファイルディスクリプタのリークが発生します。例えば,次の場合にリークが発生します。
-
ZIPファイルまたはJARファイルをオープンしている場合,明示的にクローズしないとCヒープ領域がリークします。
-
バッチサーバのusrconf.propertiesにejbserver.batch.application.exit.enabled=falseを指定した場合,java.io.File.deleteOnExit()を使用しても,バッチサーバが停止するまでファイルは削除されません。バッチサーバが停止するまでCヒープ領域がリークします。
この問題を回避するためには,リソースが正しくクローズされるようにバッチアプリケーションを実装してください。
また,ファイルやソケットなども明示的にクローズしていないと,リソース解放のタイミングが不定になります。これによって,次回以降のバッチアプリケーションの実行に影響を及ぼすおそれがあります。ファイルやソケットは明示的にクローズするようにしてください。
なお,バッチサーバの場合,コネクションの自動クローズは使用できません。バッチアプリケーション内で必ずコネクションをクローズしてください。
(d) JavaVM終了メソッドの使用
簡易構築定義ファイルでejbserver.batch.application.exit.enabledパラメタに「true」を指定すると,次のJavaVM終了メソッドが使用できます。
-
java.lang.System.exit(int)
-
java.lang.Runtime.exit(int)
-
java.lang.Runtime.halt(int)
ejbserver.batch.application.exit.enabledパラメタの設定については,「2.3.10 実行環境での設定(バッチサーバの設定)」を参照してください。なお,JavaVM終了メソッドを使用する場合の注意事項については,「2.3.11(3) JavaVM終了メソッド使用時の注意」を参照してください。
(e) シャットダウンフックの使用
簡易構築定義ファイルでejbserver.batch.application.exit.enabledパラメタに「true」を指定すると,次の場合にシャットダウンフックが使用できます。
-
JavaVM終了メソッドを呼び出した場合
-
mainメソッドがリターンした場合
-
mainスレッドで発生した例外がキャッチされなかった場合
ejbserver.batch.application.exit.enabledパラメタの設定については,「2.3.10 実行環境での設定(バッチサーバの設定)」を参照してください。
(2) バッチアプリケーションで実装できない機能
次に示す機能はバッチアプリケーションでは使用できません。「対処方法」に示す手段で対応してください。
-
標準入力からの入力
java.lang.System.inなどを使用した標準入力からの入力処理はできません。
- 対処方法
-
入力処理が必要な場合はファイルを使用してください。
-
JNIの使用
JNI経由でのネイティブライブラリの実行機能は使用できません。
- 対処方法
-
JNIを使用する場合は,コンテナ拡張ライブラリ経由で使用してください。このとき,ネイティブライブラリのロードはコンテナ拡張ライブラリ内で実施します。
-
システムプロパティのセットの置き換え
次に示すメソッドは使用できません。
-
java.lang.System.setProperties(java.util.Properties)
- 対処方法
-
java.lang.System.setProperty(String, String)を使用します。
-
-
標準出力ストリームおよび標準エラー出力ストリームの割り当てのし直し
次に示すメソッドは使用できません。
-
java.lang.System.setOut(java.io.PrintStream)
-
java.lang.System.setErr(java.io.PrintStream)
- 対処方法
-
java.lang.System.outおよびjava.lang.System.errを使用しないで,出力したいPrintStreamオブジェクトを直接使用します。
-
(3) JavaVM終了メソッド使用時の注意
簡易構築定義ファイルでejbserver.batch.application.exit.enabledパラメタに「true」を指定すると,バッチアプリケーションでJavaVM終了メソッドを使用しても,JavaVMは終了されません。この場合,JavaVM終了メソッドが呼び出したスレッドだけを終了できます。
ここでは,ejbserver.batch.application.exit.enabledパラメタに「true」を指定している場合に,JavaVM終了メソッドを使用するときの注意事項について説明します。
(a) Java言語仕様との差異
バッチアプリケーションで使用するJavaVM終了メソッドは,Java言語仕様と仕様が異なります。Java言語仕様との差異を次の表に示します。
項目 |
Java言語仕様の場合 |
バッチアプリケーションの場合 |
---|---|---|
終了対象 |
JavaVM |
JavaVM終了メソッドを呼び出したスレッド |
呼び出し以降に記述されたjavaロジック |
JavaVM終了メソッドの呼び出し以降に記述されている処理は実行されません。 |
次の場合,JavaVM終了メソッドの呼び出し以降に記述されている処理は実行されます。
|
複数回呼び出し |
使用できません。 |
次の場合に複数回呼び出されます。
|
- 参考
-
JavaVM終了メソッド実行時にJavaVMを終了したい場合は,簡易構築定義ファイルでejbserver.batch.application.exit.enabledパラメタに「false」を指定します。「false」を指定すると,JavaVM終了メソッド実行時に,バッチサーバごとJavaVMが終了します。
(b) JavaVM終了メソッドを呼び出した場合の処理
バッチアプリケーションごとに,JavaVM終了メソッドを呼び出した場合の処理を説明します。
- シングルスレッドで実装されたバッチアプリケーションでJavaVM終了メソッドを呼び出した場合
-
mainスレッドを終了し,バッチアプリケーションの実行を終了します。
JavaVM終了メソッドが複数回呼び出された場合の動作を次の表に示します。
表2‒11 JavaVM終了メソッドが複数回呼び出された場合の動作(シングルスレッドで実装されたバッチアプリケーションの場合) 項番
項目
動作
1
バッチアプリケーション実行機能への終了通知
1回目のJavaVM終了メソッド呼び出し時にだけ終了を通知します。
2回目以降のJavaVM終了メソッド呼び出し時には通知しません。
2
終了コードの返却
1回目のJavaVM終了メソッド呼び出し時に引数に指定された終了コードが有効となります。
2回目以降のJavaVM終了メソッド呼び出し時に引数に指定された終了コードは無効となります。
3
JavaVM終了メソッドを呼び出したスレッド
JavaVM終了メソッドの呼び出し回数に関係なく,スレッドが終了します。
- マルチスレッドで実装されたバッチアプリケーションでJavaVM終了メソッドを呼び出した場合
-
JavaVM終了メソッドを呼び出したスレッドが終了します。それ以外のスレッドの処理は,JavaVM終了メソッドがどのスレッドから呼び出されたかによって,異なります。
-
mainスレッドでJavaVM終了メソッドを呼び出した場合,mainメソッドがリターンした場合,またはmainスレッドで発生した例外がキャッチされなかった場合
バッチアプリケーション実行機能が,すべての実行中のユーザスレッドに対して,java.lang.Threadクラスのinterruptを実行します。
-
ユーザスレッドでJavaVM終了メソッドを呼び出した場合
バッチアプリケーション実行機能が,次に示すスレッド以外の,すべての実行中のユーザスレッドに対して,java.lang.Threadクラスのinterruptを実行します。
・JavaVM終了メソッドを呼び出したユーザスレッド
・mainスレッド
バッチアプリケーション実行機能は,ユーザスレッドを呼び出しているmainスレッドに対して,メソッドキャンセルを実行します。メソッドキャンセルが成功した場合,mainスレッドが終了し,バッチアプリケーションが終了します。メソッドキャンセルが失敗した場合は,バッチサーバごとJavaVMが終了します。
ユーザスレッドでのJavaVM終了メソッド呼び出しは,メソッドキャンセルが失敗することがあるため,推奨しません。
どちらの場合も,mainスレッドが終了すると,ユーザスレッドが残っているかどうかに関係なく,次のバッチアプリケーションの開始を受け付けられます。
-