Hitachi

Cosminexus V11 アプリケーションサーバ 機能解説 拡張編


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) バッチアプリケーションで実装できない機能

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

(3) JavaVM終了メソッド使用時の注意

簡易構築定義ファイルでejbserver.batch.application.exit.enabledパラメタに「true」を指定すると,バッチアプリケーションでJavaVM終了メソッドを使用しても,JavaVMは終了されません。この場合,JavaVM終了メソッドが呼び出したスレッドだけを終了できます。

ここでは,ejbserver.batch.application.exit.enabledパラメタに「true」を指定している場合に,JavaVM終了メソッドを使用するときの注意事項について説明します。

(a) Java言語仕様との差異

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

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

項目

Java言語仕様の場合

バッチアプリケーションの場合

終了対象

JavaVM

JavaVM終了メソッドを呼び出したスレッド

呼び出し以降に記述されたjavaロジック

JavaVM終了メソッドの呼び出し以降に記述されている処理は実行されません。

次の場合,JavaVM終了メソッドの呼び出し以降に記述されている処理は実行されます。

  • JavaVM終了メソッドがtryブロックに記述された場合は,対応するfinallyブロックが実行されます。※1

  • スレッドにjava.lang.Thread.UncaughtExceptionHandlerが登録されていた場合は,UncaughtExceptionHandlerが実行されます。※1

複数回呼び出し

使用できません。

次の場合に複数回呼び出されます。

  • JavaVM終了メソッドを呼び出したスレッドと同一のfinallyブロックから,JavaVM終了メソッドを呼び出す場合

  • バッチアプリケーションから起動された複数のユーザスレッド※2から,JavaVM終了メソッドを呼び出す場合

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

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

  • finallyブロック内およびfinallyブロック内で呼び出されたメソッド内に,時間が掛かるJavaプログラム処理が記述された場合

  • java.lang.Thread.UncaughtExceptionHandlerに,時間が掛かるJavaプログラム処理が記述された場合

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

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

  • run()メソッドの中でinterruptedExceptionがキャッチされると,ユーザスレッドは終了されないで残ります。

  • ユーザスレッドが残っていても,mainスレッドが終了していれば,次のアプリケーションの開始を受け付けられますが,メモリリークが発生します。

参考

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スレッドが終了すると,ユーザスレッドが残っているかどうかに関係なく,次のバッチアプリケーションの開始を受け付けられます。