2.3.11 バッチアプリケーション作成時の注意

ここでは,バッチアプリケーション作成時に注意が必要となる処理や,バッチアプリケーションでは使用できない機能について説明します。これらの内容を確認の上,バッチアプリケーションを作成してください。

<この項の構成>
(1) 注意が必要な処理
(2) バッチアプリケーションで実装できない機能
(3) JavaVM終了メソッド使用時の注意

(1) 注意が必要な処理

次に示す処理は,バッチアプリケーションを作成する際に注意が必要です。

ファイルやディレクトリの操作

バッチアプリケーションでは,次に示すファイルやディレクトリは操作しないでください。

また,バッチアプリケーションでファイルやディレクトリを扱う場合,ファイルやディレクトリのパスに相対パスを使用できません。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");

スレッドの使用

バッチサーバは,バッチアプリケーションが作成および開始したスレッドの終了を待ちません。バッチアプリケーション内でスレッドを使用する場合は,バッチアプリケーションを終了する前に,開始したすべてのユーザスレッドを完了するように実装してください。また,ユーザスレッドはメソッドキャンセルの対象外です。

なお,簡易構築定義ファイルでejbserver.batch.application.exit.enabledパラメタで「true」を指定した場合には,次の点に注意してください。

バッチアプリケーションが作成したスレッドが残っていると,バッチアプリケーションのクラスや使用したリソースは解放されません。このため,次にバッチアプリケーションを開始しようとすると,バッチアプリケーションの開始に失敗するおそれがあります。また,ユーザスレッド内では,次のバッチサーバの機能を呼び出すことはできません。

●JavaVM終了時のリソースの自動クローズ

バッチサーバではサーバのJavaVM上でバッチアプリケーションを実行します。このため,JavaVM終了による自動的なリソースのクローズ処理を期待した実装をしている場合は,メモリやファイルディスクリプタのリークが発生します。例えば,次の場合にリークが発生します。

この問題を回避するためには,リソースが正しくクローズされるようにバッチアプリケーションを実装してください。

また,ファイルやソケットなども明示的にクローズしていないと,リソース解放のタイミングが不定になります。これによって,次回以降のバッチアプリケーションの実行に影響を及ぼすおそれがあります。ファイルやソケットは明示的にクローズするようにしてください。

なお,バッチサーバの場合,コネクションの自動クローズは使用できません。バッチアプリケーション内で必ずコネクションをクローズしてください。

●JavaVM終了メソッドの使用

簡易構築定義ファイルでejbserver.batch.application.exit.enabledパラメタに「true」を指定すると,次のJavaVM終了メソッドが使用できます。

ejbserver.batch.application.exit.enabledパラメタの設定については,「2.3.10 実行環境での設定(バッチサーバの設定)」を参照してください。なお,JavaVM終了メソッドを使用する場合の注意事項については,「(3) JavaVM終了メソッド使用時の注意」を参照してください。

●シャットダウンフックの使用

簡易構築定義ファイルでejbserver.batch.application.exit.enabledパラメタに「true」を指定すると,次の場合にシャットダウンフックが使用できます。

ejbserver.batch.application.exit.enabledパラメタの設定については,「2.3.10 実行環境での設定(バッチサーバの設定)」を参照してください。

(2) バッチアプリケーションで実装できない機能

次に示す機能はバッチアプリケーションでは使用できません。「対処方法」に示す手段で対応してください。

●標準入力からの入力

java.lang.System.inなどを使用した標準入力からの入力処理はできません。

対処方法
入力処理が必要な場合はファイルを使用してください。
●JNIの使用

JNI経由でのネイティブライブラリの実行機能は使用できません。

対処方法
JNIを使用する場合は,コンテナ拡張ライブラリ経由で使用してください。このとき,ネイティブライブラリのロードはコンテナ拡張ライブラリ内で実施します。
●システムプロパティのセットの置き換え

次に示すメソッドは使用できません。

対処方法
java.lang.System.setProperty(String, String)を使用します。
●標準出力ストリームおよび標準エラー出力ストリームの割り当てのし直し

次に示すメソッドは使用できません。

対処方法
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終了メソッドを使用するときの注意事項について説明します。

●Java言語仕様との差異

バッチアプリケーションで使用するJavaVM終了メソッドは,Java言語仕様と仕様が異なります。Java言語仕様との差異を次の表に示します。

表2-10 Java言語仕様との差異

項目Java言語仕様の場合バッチアプリケーションの場合
終了対象JavaVMJavaVM終了メソッドを呼び出したスレッド
呼び出し以降に記述されたjavaロジックJavaVM終了メソッドの呼び出し以降に記述されている処理は実行されません。次の場合,JavaVM終了メソッドの呼び出し以降に記述されている処理は実行されます。
  • JavaVM終了メソッドがtryブロックに記述された場合は,対応するfinallyブロックが実行されます。※1
  • スレッドにjava.lang.Thread.UncaughtExceptionHandlerが登録されていた場合は,UncaughtExceptionHandlerが実行されます。※1
複数回呼び出し使用できません。次の場合に複数回呼び出されます。
  • JavaVM終了メソッドを呼び出したスレッドと同一のfinallyブロックから,JavaVM終了メソッドを呼び出す場合
  • バッチアプリケーションから起動された複数のユーザスレッド※2から,JavaVM終了メソッドを呼び出す場合

注※1 finallyブロック内およびfinallyブロック内で呼び出されたメソッド内で例外が発生し,その例外がfinallyブロックでキャッチされないでfinallyブロックの実行が途中で中断された場合は,スレッドが終了できないときがあります。

また,次の場合,スレッドの終了に時間が掛かったり,スレッドが終了できなかったりするときがあります。

なお,時間の掛かるJavaプログラムの処理には,無限ループ,synchronized文によるモニタ待ち,java.lang.wait()による待ちなどがあります。

注※2 ユーザスレッドとは,バッチアプリケーションが作成した子スレッドを示します。ユーザスレッドを使用している場合は,次の点に注意してください。


参考
JavaVM終了メソッド実行時にJavaVMを終了したい場合は,簡易構築定義ファイルでejbserver.batch.application.exit.enabledパラメタに「false」を指定します。「false」を指定すると,JavaVM終了メソッド実行時に,バッチサーバごとJavaVMが終了します。
●JavaVM終了メソッドを呼び出した場合の処理

バッチアプリケーションごとに,JavaVM終了メソッドを呼び出した場合の処理を説明します。

シングルスレッドで実装されたバッチアプリケーションでJavaVM終了メソッドを呼び出した場合
mainスレッドを終了し,バッチアプリケーションの実行を終了します。
JavaVM終了メソッドが複数回呼び出された場合の動作を次の表に示します。

表2-11 JavaVM終了メソッドが複数回呼び出された場合の動作(シングルスレッドで実装されたバッチアプリケーションの場合)

項番項目動作
1バッチアプリケーション実行機能への終了通知1回目のJavaVM終了メソッド呼び出し時にだけ終了を通知します。
2回目以降のJavaVM終了メソッド呼び出し時には通知しません。
2終了コードの返却1回目のJavaVM終了メソッド呼び出し時に引数に指定された終了コードが有効となります。
2回目以降のJavaVM終了メソッド呼び出し時に引数に指定された終了コードは無効となります。
3JavaVM終了メソッドを呼び出したスレッドJavaVM終了メソッドの呼び出し回数に関係なく,スレッドが終了します。
マルチスレッドで実装されたバッチアプリケーションでJavaVM終了メソッドを呼び出した場合
JavaVM終了メソッドを呼び出したスレッドが終了します。それ以外のスレッドの処理は,JavaVM終了メソッドがどのスレッドから呼び出されたかによって,異なります。
  • mainスレッドでJavaVM終了メソッドを呼び出した場合,mainメソッドがリターンした場合,またはmainスレッドで発生した例外がキャッチされなかった場合
    バッチアプリケーション実行機能が,すべての実行中のユーザスレッドに対して,java.lang.Threadクラスのinterruptを実行します。
  • ユーザスレッドでJavaVM終了メソッドを呼び出した場合
    バッチアプリケーション実行機能が,次に示すスレッド以外の,すべての実行中のユーザスレッドに対して,java.lang.Threadクラスのinterruptを実行します。
    ・JavaVM終了メソッドを呼び出したユーザスレッド
    ・mainスレッド
    バッチアプリケーション実行機能は,ユーザスレッドを呼び出しているmainスレッドに対して,メソッドキャンセルを実行します。メソッドキャンセルが成功した場合,mainスレッドが終了し,バッチアプリケーションが終了します。メソッドキャンセルが失敗した場合は,バッチサーバごとJavaVMが終了します。
    ユーザスレッドでのJavaVM終了メソッド呼び出しは,メソッドキャンセルが失敗することがあるため,推奨しません。
どちらの場合も,mainスレッドが終了すると,ユーザスレッドが残っているかどうかに関係なく,次のバッチアプリケーションの開始を受け付けられます。